Merge "Add test for augmented FillRequest#getInlineSuggestionsRequest" into rvc-dev
diff --git a/apps/CameraITS/pymodules/its/cv2image.py b/apps/CameraITS/pymodules/its/cv2image.py
index d62172c..b2e9e2f 100644
--- a/apps/CameraITS/pymodules/its/cv2image.py
+++ b/apps/CameraITS/pymodules/its/cv2image.py
@@ -31,6 +31,7 @@
 CHART_SCALE_STOP = 1.35
 CHART_SCALE_STEP = 0.025
 
+FOV_THRESH_SUPER_TELE = 45
 FOV_THRESH_TELE = 60
 FOV_THRESH_WFOV = 90
 
diff --git a/apps/CameraITS/tests/scene3/scene3.pdf b/apps/CameraITS/tests/scene3/scene3.pdf
index 4c787b1..0db93f8 100644
--- a/apps/CameraITS/tests/scene3/scene3.pdf
+++ b/apps/CameraITS/tests/scene3/scene3.pdf
Binary files differ
diff --git a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
index 75b7a5d..94e5c6b 100644
--- a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
+++ b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
@@ -36,6 +36,50 @@
 TRANS_REF_MATRIX = np.array([0, 0, 0])
 
 
+def select_ids_to_test(ids, props, chart_distance):
+    """Determine the best 2 cameras to test for the rig used.
+
+    Cameras are pre-filtered to only include supportable cameras.
+    Supportable cameras are: YUV(RGB), RAW(Bayer)
+
+    Args:
+        ids:            unicode string; physical camera ids
+        props:          dict; physical camera properties dictionary
+        chart_distance: float; distance to chart in meters
+    Returns:
+        test_ids to be tested
+    """
+    chart_distance = abs(chart_distance)*100  # convert M to CM
+    test_ids = []
+    for i in ids:
+        sensor_size = props[i]['android.sensor.info.physicalSize']
+        focal_l = props[i]['android.lens.info.availableFocalLengths'][0]
+        diag = math.sqrt(sensor_size['height'] ** 2 +
+                         sensor_size['width'] ** 2)
+        fov = round(2 * math.degrees(math.atan(diag / (2 * focal_l))), 2)
+        print 'Camera: %s, FoV: %.2f, chart_distance: %.1fcm' % (
+                i, fov, chart_distance)
+        # determine best combo with rig used or recommend different rig
+        if its.cv2image.FOV_THRESH_TELE < fov < its.cv2image.FOV_THRESH_WFOV:
+            test_ids.append(i)  # RFoV camera
+        elif fov < its.cv2image.FOV_THRESH_SUPER_TELE:
+            print 'Skipping camera. Not appropriate multi-camera testing.'
+            continue  # super-TELE camera
+        elif (fov <= its.cv2image.FOV_THRESH_TELE and
+              np.isclose(chart_distance, its.cv2image.CHART_DISTANCE_RFOV, rtol=0.1)):
+            test_ids.append(i)  # TELE camera in RFoV rig
+        elif (fov >= its.cv2image.FOV_THRESH_WFOV and
+              np.isclose(chart_distance, its.cv2image.CHART_DISTANCE_WFOV, rtol=0.1)):
+            test_ids.append(i)  # WFoV camera in WFoV rig
+        else:
+            print 'Skipping camera. Not appropriate for test rig.'
+
+    e_msg = 'Error: started with 2+ cameras, reduced to <2. Wrong test rig?'
+    e_msg += '\ntest_ids: %s' % str(test_ids)
+    assert len(test_ids) >= 2, e_msg
+    return test_ids[0:2]
+
+
 def determine_valid_out_surfaces(cam, props, fmt, cap_camera_ids, sizes):
     """Determine a valid output surfaces for captures.
 
@@ -331,7 +375,11 @@
         props = cam.get_camera_properties()
         its.caps.skip_unless(its.caps.read_3a(props) and
                              its.caps.per_frame_control(props) and
-                             its.caps.logical_multi_camera(props))
+                             its.caps.logical_multi_camera(props) and
+                             its.caps.backward_compatible(props))
+        debug = its.caps.debug_mode()
+        avail_fls = props['android.lens.info.availableFocalLengths']
+        pose_reference = props['android.lens.poseReference']
 
         # Convert chart_distance for lens facing back
         if props['android.lens.facing'] == LENS_FACING_BACK:
@@ -339,37 +387,40 @@
             print 'lens facing BACK'
             chart_distance *= -1
 
-        # Find physical camera IDs and those that support RGB raw
+        # find physical camera IDs
         ids = its.caps.logical_multi_camera_physical_ids(props)
-        props_physical = {}
+        physical_props = {}
         physical_ids = []
         physical_raw_ids = []
         for i in ids:
-            # Find YUV capable physical cameras
-            prop = cam.get_camera_properties_by_id(i)
-            sub_camera_pose_reference = prop['android.lens.poseReference']
-            if sub_camera_pose_reference == UNDEFINED_REFERENCE:
+            physical_props[i] = cam.get_camera_properties_by_id(i)
+            if physical_props[i]['android.lens.poseReference'] == UNDEFINED_REFERENCE:
                 continue
-            physical_ids.append(i)
-            props_physical[i] = prop
-            # Find first 2 RAW+RGB capable physical cameras
-            if (its.caps.raw16(prop) and not its.caps.mono_camera(props)
-                        and len(physical_raw_ids) < 2):
+            # find YUV+RGB capable physical cameras
+            if (its.caps.backward_compatible(physical_props[i]) and
+                        not its.caps.mono_camera(physical_props[i])):
+                physical_ids.append(i)
+            # find RAW+RGB capable physical cameras
+            if (its.caps.backward_compatible(physical_props[i]) and
+                        not its.caps.mono_camera(physical_props[i]) and
+                        its.caps.raw16(physical_props[i])):
                 physical_raw_ids.append(i)
 
-        debug = its.caps.debug_mode()
-        avail_fls = props['android.lens.info.availableFocalLengths']
-        pose_reference = props['android.lens.poseReference']
-
-        # Find highest resolution image and determine formats
+        # determine formats and select cameras
         fmts = ['yuv']
+        if len(physical_raw_ids) >= 2:
+            fmts.insert(0, 'raw')  # add RAW to analysis if enough cameras
+            print 'Selecting RAW+RGB supported cameras'
+            physical_raw_ids = select_ids_to_test(physical_raw_ids,
+                                                  physical_props,
+                                                  chart_distance)
+        print 'Selecting YUV+RGB cameras'
         its.caps.skip_unless(len(physical_ids) >= 2)
-        if len(physical_raw_ids) == 2:
-            fmts.insert(0, 'raw')  # insert in first location in list
-        else:
-            physical_ids = ids[0:2]
+        physical_ids = select_ids_to_test(physical_ids,
+                                          physical_props,
+                                          chart_distance)
 
-        # do captures for different formats
+        # do captures for valid formats
         caps = {}
         for i, fmt in enumerate(fmts):
             physical_sizes = {}
@@ -379,7 +430,7 @@
                 capture_cam_ids = physical_raw_ids
 
             for physical_id in capture_cam_ids:
-                configs = props_physical[physical_id]['android.scaler.streamConfigurationMap']\
+                configs = physical_props[physical_id]['android.scaler.streamConfigurationMap']\
                                    ['availableStreamConfigurations']
                 if fmt == 'raw':
                     fmt_codes = 0x20
@@ -395,7 +446,7 @@
             out_surfaces = determine_valid_out_surfaces(
                     cam, props, fmt, capture_cam_ids, physical_sizes)
             caps = take_images(
-                    cam, caps, props_physical, fmt, capture_cam_ids, out_surfaces, debug)
+                    cam, caps, physical_props, fmt, capture_cam_ids, out_surfaces, debug)
 
     # process images for correctness
     for j, fmt in enumerate(fmts):
@@ -414,7 +465,7 @@
         for i in capture_cam_ids:
             # process image
             img = its.image.convert_capture_to_rgb_image(
-                    caps[(fmt, i)], props=props_physical[i])
+                    caps[(fmt, i)], props=physical_props[i])
             size[i] = (caps[fmt, i]['width'], caps[fmt, i]['height'])
 
             # save images if debug
@@ -431,7 +482,7 @@
                 img = img.astype(np.uint8)
 
             # load parameters for each physical camera
-            ical = props_physical[i]['android.lens.intrinsicCalibration']
+            ical = physical_props[i]['android.lens.intrinsicCalibration']
             assert len(ical) == 5, 'android.lens.instrisicCalibration incorrect.'
             k[i] = np.array([[ical[0], ical[4], ical[2]],
                              [0, ical[1], ical[3]],
@@ -440,13 +491,13 @@
                 print 'Camera %s' % i
                 print ' k:', k[i]
 
-            rotation = np.array(props_physical[i]['android.lens.poseRotation'])
+            rotation = np.array(physical_props[i]['android.lens.poseRotation'])
             if j == 0:
                 print ' rotation:', rotation
             assert len(rotation) == 4, 'poseRotation has wrong # of params.'
             r[i] = rotation_matrix(rotation)
 
-            t[i] = np.array(props_physical[i]['android.lens.poseTranslation'])
+            t[i] = np.array(physical_props[i]['android.lens.poseTranslation'])
             if j == 0:
                 print ' translation:', t[i]
             assert len(t[i]) == 3, 'poseTranslation has wrong # of params.'
@@ -469,8 +520,8 @@
                 print 'r:', r[i]
 
             # Correct lens distortion to image (if available)
-            if its.caps.distortion_correction(props_physical[i]) and fmt == 'raw':
-                distort = np.array(props_physical[i]['android.lens.distortion'])
+            if its.caps.distortion_correction(physical_props[i]) and fmt == 'raw':
+                distort = np.array(physical_props[i]['android.lens.distortion'])
                 assert len(distort) == 5, 'distortion has wrong # of params.'
                 cv2_distort = np.array([distort[0], distort[1],
                                         distort[3], distort[4],
@@ -490,7 +541,7 @@
             # Undo zoom to image (if applicable). Assume that the maximum
             # physical YUV image size is close to active array size.
             if fmt == 'yuv':
-                ar = props_physical[i]['android.sensor.info.activeArraySize']
+                ar = physical_props[i]['android.sensor.info.activeArraySize']
                 arw = ar['right'] - ar['left']
                 arh = ar['bottom'] - ar['top']
                 cr = caps[(fmt, i)]['metadata']['android.scaler.cropRegion']
@@ -504,7 +555,7 @@
                 circle[i][2] = circle[i][2] / zoom_ratio
 
             # Find focal length & sensor size
-            fl[i] = props_physical[i]['android.lens.info.availableFocalLengths'][0]
+            fl[i] = physical_props[i]['android.lens.info.availableFocalLengths'][0]
             sensor_diag[i] = math.sqrt(size[i][0] ** 2 + size[i][1] ** 2)
 
         i_ref, i_2nd = define_reference_camera(pose_reference, cam_reference)
diff --git a/apps/CtsVerifier/res/layout/organization_info.xml b/apps/CtsVerifier/res/layout/organization_info.xml
index 320fb8c..4921012 100644
--- a/apps/CtsVerifier/res/layout/organization_info.xml
+++ b/apps/CtsVerifier/res/layout/organization_info.xml
@@ -37,16 +37,6 @@
                     android:windowSoftInputMode="adjustPan"
                     android:padding="16dp"
                     android:layout_weight="1"/>
-            <EditText android:id="@+id/organization_color_edit_text"
-                    android:layout_width="0dp"
-                    android:layout_height="wrap_content"
-                    android:hint="@string/provisioning_byod_organization_color_hint"
-                    android:gravity="top|start"
-                    android:digits="#0123456789abcdefABCDEF"
-                    android:inputType="textCapCharacters"
-                    android:windowSoftInputMode="adjustPan"
-                    android:padding="16dp"
-                    android:layout_weight="1" />
         </LinearLayout>
 
         <LinearLayout
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 078d24e..85aa307 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -3258,18 +3258,15 @@
 
     <string name="provisioning_byod_organization_info">Organization Info</string>
     <string name="provisioning_byod_organization_name_hint">Name</string>
-    <string name="provisioning_byod_organization_color_hint">#FF00FF</string>
     <string name="provisioning_byod_set_organization_info_button_text">Set</string>
     <string name="provisioning_byod_organization_info_instructions">
     This test verifies that the Organization Info was set correctly.
     You can only do this test after you have done "select work lock" test.\n
         1. Enter your organization name.\n
-        2. Enter a valid color code.\n
-        3. Press the Set button to set organization Info.\n
-        4. Press the Go button to open a dialog to confirm work credentials.\n
+        2. Press the Set button to set organization Info.\n
+        3. Press the Go button to open a dialog to confirm work credentials.\n
         (If this device has a separate app for work settings, ignore the Go button and open the work lock screen manually to confirm, if necessary.)\n
-        5. Verify that the background color of the resulting dialog is as set by you.\n
-        6. Verify that the header text has organization name as set by you.\n
+        4. Verify that the header text has organization name as set by you.\n
     </string>
 
     <string name="provisioning_byod_no_secure_lockscreen">No work lockscreen password set. Please run \"Select work lock test\" and rerun this test</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
index 66ff174..0f76f61 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
@@ -27,7 +27,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.graphics.Color;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -367,7 +366,6 @@
         } else if (ACTION_CLEAR_NOTIFICATION.equals(action)) {
             mNotificationManager.cancel(NOTIFICATION_ID);
         } else if (ACTION_TEST_SELECT_WORK_CHALLENGE.equals(action)) {
-            mDevicePolicyManager.setOrganizationColor(mAdminReceiverComponent, Color.BLUE);
             mDevicePolicyManager.setOrganizationName(mAdminReceiverComponent, getResources()
                     .getString(R.string.provisioning_byod_confirm_work_credentials_header));
             startActivity(new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD));
@@ -389,10 +387,6 @@
                         .getStringExtra(OrganizationInfoTestActivity.EXTRA_ORGANIZATION_NAME);
                 mDevicePolicyManager.setOrganizationName(mAdminReceiverComponent, organizationName);
             }
-            final int organizationColor = intent.getIntExtra(
-                    OrganizationInfoTestActivity.EXTRA_ORGANIZATION_COLOR,
-                    mDevicePolicyManager.getOrganizationColor(mAdminReceiverComponent));
-            mDevicePolicyManager.setOrganizationColor(mAdminReceiverComponent, organizationColor);
         } else if (ACTION_TEST_PARENT_PROFILE_PASSWORD.equals(action)) {
             startActivity(new Intent(DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD));
         }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OrganizationInfoTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OrganizationInfoTestActivity.java
index 7c5f374..6bf5cae 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OrganizationInfoTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OrganizationInfoTestActivity.java
@@ -17,11 +17,9 @@
 package com.android.cts.verifier.managedprovisioning;
 
 import android.content.Intent;
-import android.graphics.Color;
 import android.os.Bundle;
 import android.view.View;
 import android.widget.EditText;
-import android.widget.Toast;
 
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
@@ -33,9 +31,6 @@
         implements View.OnClickListener {
 
     public static final String EXTRA_ORGANIZATION_NAME = "extra_organization_name";
-    public static final String EXTRA_ORGANIZATION_COLOR = "extra_organization_color";
-
-    private int mOrganizationColor;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -57,25 +52,10 @@
                     R.id.organization_name_edit_text);
             Intent intent = new Intent(ByodHelperActivity.ACTION_SET_ORGANIZATION_INFO);
             intent.putExtra(EXTRA_ORGANIZATION_NAME, organizationNameEditText.getText().toString());
-            if (isOrganizationColorSet()) {
-                intent.putExtra(EXTRA_ORGANIZATION_COLOR, mOrganizationColor);
-            }
             startActivity(intent);
         } else if (view.getId() == R.id.go_button) {
             Intent intent = new Intent(ByodHelperActivity.ACTION_LAUNCH_CONFIRM_WORK_CREDENTIALS);
             startActivity(intent);
         }
     }
-
-    private boolean isOrganizationColorSet() {
-        EditText organizationColorEditText = (EditText) findViewById(
-                R.id.organization_color_edit_text);
-        try {
-            mOrganizationColor = Color.parseColor(organizationColorEditText.getText().toString());
-        } catch (Exception e) {
-            Toast.makeText(this, "Not a valid Color value", Toast.LENGTH_SHORT).show();
-            return false;
-        }
-        return true;
-    }
 }
diff --git a/hostsidetests/adb/Android.mk b/hostsidetests/adb/Android.mk
new file mode 100644
index 0000000..292bc18
--- /dev/null
+++ b/hostsidetests/adb/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_COMPATIBILITY_SUITE := cts vts10 general-tests
+LOCAL_CTS_TEST_PACKAGE := android.host.adb
+LOCAL_MODULE := CtsAdbHostTestCases
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util
+LOCAL_JAVA_RESOURCE_FILES := $(HOST_OUT_EXECUTABLES)/check_ms_os_desc
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/adb/AndroidTest.xml b/hostsidetests/adb/AndroidTest.xml
new file mode 100755
index 0000000..46fcc98
--- /dev/null
+++ b/hostsidetests/adb/AndroidTest.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration description="Config for the CTS adb host tests">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="bionic" />
+    <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" >
+        <option name="jar" value="CtsAdbHostTestCases.jar" />
+    </test>
+</configuration>
diff --git a/hostsidetests/adb/OWNERS b/hostsidetests/adb/OWNERS
new file mode 100644
index 0000000..7529cb9
--- /dev/null
+++ b/hostsidetests/adb/OWNERS
@@ -0,0 +1 @@
+include platform/system/core:/janitors/OWNERS
diff --git a/hostsidetests/adb/src/android/adb/cts/AdbHostTest.java b/hostsidetests/adb/src/android/adb/cts/AdbHostTest.java
new file mode 100644
index 0000000..f388cc3
--- /dev/null
+++ b/hostsidetests/adb/src/android/adb/cts/AdbHostTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.adb.cts;
+
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IDeviceTest;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class AdbHostTest extends DeviceTestCase implements IDeviceTest {
+    // TODO: there are too many copies of this in CTS!
+    public static File copyResourceToTempFile(String resName) throws IOException {
+        InputStream is = AdbHostTest.class.getResourceAsStream(resName);
+        File tf = File.createTempFile("AdbHostTest", ".tmp");
+        FileOutputStream os = new FileOutputStream(tf);
+        byte[] buf = new byte[8192];
+        int length;
+        while ((length = is.read(buf)) != -1) {
+            os.write(buf, 0, length);
+        }
+        os.flush();
+        os.close();
+        tf.deleteOnExit();
+        return tf;
+    }
+
+    public void testHasMsOsDescriptors() throws Exception {
+        File check_ms_os_desc = copyResourceToTempFile("/check_ms_os_desc");
+        check_ms_os_desc.setExecutable(true);
+
+        // ANDROID_SERIAL is already set correctly in our environment.
+        ProcessBuilder pb = new ProcessBuilder(check_ms_os_desc.getAbsolutePath());
+        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+        pb.redirectErrorStream(true);
+        Process p = pb.start();
+        int result = p.waitFor();
+        BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
+        String line;
+        StringBuilder output = new StringBuilder();
+        while ((line = br.readLine()) != null) {
+            output.append(line + "\n");
+        }
+        assertTrue("check_ms_os_desc failed:\n" + output, result == 0);
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk
index 543f310..3360f07 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk
index c801897..0996efe 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
index b1d07e2..1e57012 100644
--- a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
@@ -50,6 +50,7 @@
 import android.os.Environment;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
+import android.provider.MediaStore;
 import android.support.test.uiautomator.UiDevice;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
@@ -196,6 +197,8 @@
         // Rename to ensure that stats are updated
         video.renameTo(new File(dir, System.nanoTime() + ".PnG"));
 
+        MediaStore.waitForIdle(getContext().getContentResolver());
+
         final ExternalStorageStats afterRename = stats.queryExternalStatsForUser(UUID_DEFAULT, user);
 
         assertMostlyEquals(17 * MB_IN_BYTES, afterRename.getTotalBytes() - before.getTotalBytes());
diff --git a/hostsidetests/graphics/gpuprofiling/app/Android.bp b/hostsidetests/graphics/gpuprofiling/app/Android.bp
index 134e0cc..6c05ece 100644
--- a/hostsidetests/graphics/gpuprofiling/app/Android.bp
+++ b/hostsidetests/graphics/gpuprofiling/app/Android.bp
@@ -17,6 +17,7 @@
     srcs: [
         "android_graphics_cts_GpuProfilingData.cpp",
     ],
+    test_suites: ["cts"],
     compile_multilib: "both",
     multilib: {
         lib32: {
diff --git a/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java b/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java
index 5f24e6c..d847e3c 100644
--- a/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java
+++ b/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java
@@ -99,6 +99,7 @@
     public void setup() throws Exception {
         assumeTrue(hasIncrementalFeature());
         mBuildHelper = new CompatibilityBuildHelper(getBuild());
+        assumeTrue(adbBinarySupportsIncremental());
         uninstallApp(TEST_APP_PACKAGE_NAME);
         assertFalse(isPackageInstalled(TEST_APP_PACKAGE_NAME));
     }
@@ -402,4 +403,9 @@
     private boolean hasIncrementalFeature() throws Exception {
         return hasDeviceFeature(FEATURE_INCREMENTAL_DELIVERY);
     }
+
+    private boolean adbBinarySupportsIncremental() throws Exception {
+        return !installWithAdbInstaller(TEST_APP_BASE_APK_NAME).contains(
+                "Unknown option --incremental");
+    }
 }
diff --git a/hostsidetests/securitybulletin/AndroidTest.xml b/hostsidetests/securitybulletin/AndroidTest.xml
index 42b22c9..fe1e89c 100644
--- a/hostsidetests/securitybulletin/AndroidTest.xml
+++ b/hostsidetests/securitybulletin/AndroidTest.xml
@@ -158,6 +158,7 @@
         <!--__________________-->
         <!-- Bulletin 2018-01 -->
         <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+        <option name="push" value="CVE-2018-9527->/data/local/tmp/CVE-2018-9527" />
 
         <!--__________________-->
         <!-- Bulletin 2018-02 -->
@@ -188,7 +189,6 @@
         <!--__________________-->
         <!-- Bulletin 2018-11 -->
         <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2018-9536->/data/local/tmp/CVE-2018-9536" />
         <option name="push" value="CVE-2018-9539->/data/local/tmp/CVE-2018-9539" />
 
         <!--__________________-->
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9536/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/Android.bp
similarity index 73%
rename from hostsidetests/securitybulletin/securityPatch/CVE-2018-9536/Android.bp
rename to hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/Android.bp
index 16f9474..c6b3bd9 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9536/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/Android.bp
@@ -13,15 +13,9 @@
 // limitations under the License.
 
 cc_test {
-    name: "CVE-2018-9536",
+    name: "CVE-2018-9527",
     defaults: ["cts_hostsidetests_securitybulletin_defaults"],
     srcs: ["poc.cpp"],
-    include_dirs: [
-        "external/aac/libFDK/include",
-        "external/aac/libSYS/include",
-        "cts/hostsidetests/securitybulletin/securityPatch/includes",
-    ],
-    shared_libs: [
-        "libbluetooth"
-    ],
+    include_dirs: ["./external/tremolo"],
+    shared_libs: ["libvorbisidec"],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/poc.cpp
new file mode 100644
index 0000000..fa32eb8
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/poc.cpp
@@ -0,0 +1,104 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <string.h>
+#include <stdlib.h>
+#define REF_COUNT     1
+#define DECODE_PACKET 1
+
+extern "C" {
+#include <Tremolo/codec_internal.h>
+
+int _vorbis_unpack_books(vorbis_info *vi, oggpack_buffer *opb);
+int _vorbis_unpack_info(vorbis_info *vi, oggpack_buffer *opb);
+int _vorbis_unpack_comment(vorbis_comment *vc, oggpack_buffer *opb);
+}
+
+const uint8_t packInfoData[] = { 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0xBB, 0x00,
+        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0xBB, 0x01, 0xFF, 0xFF, 0xFF, 0xFF };
+
+unsigned char unpackBookData[] = { 0x00, 0x42, 0x43, 0x56, 0x1E, 0x00, 0x10,
+        0x00, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x10, 0x0A, 0xFF, 0x00, 0x00,
+        0x00, 0x06, 0xD0, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x1D, 0x00, 0x00, 0x00,
+        0x2C, 0x00, 0x03, 0x3C, 0x51, 0x04, 0x34, 0x4F, 0x04, 0x00, 0x40, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x40, 0x00, 0x00, 0x01, 0x4F, 0xF4,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
+
+unsigned char bufData[] = { 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xE7,
+        0x00, 0x00, 0xE9, 0x00 };
+
+static void makeBitReader(const void *data, size_t size, ogg_buffer *buf,
+                          ogg_reference *ref, oggpack_buffer *bits) {
+    buf->data = (uint8_t *) data;
+    buf->size = size;
+    buf->refcount = REF_COUNT;
+
+    ref->buffer = buf;
+    ref->length = size;
+    oggpack_readinit(bits, ref);
+}
+
+int main() {
+    ogg_buffer buf;
+    ogg_reference ref;
+    oggpack_buffer bits;
+
+    memset(&buf, 0, sizeof(ogg_buffer));
+    memset(&ref, 0, sizeof(ogg_reference));
+    memset(&bits, 0, sizeof(oggpack_buffer));
+
+    makeBitReader(packInfoData, sizeof(packInfoData), &buf, &ref, &bits);
+
+    vorbis_info *mVi = new vorbis_info;
+    vorbis_info_init(mVi);
+
+    int ret = _vorbis_unpack_info(mVi, &bits);
+    if (!ret) {
+        memset(&buf, 0, sizeof(ogg_buffer));
+        memset(&ref, 0, sizeof(ogg_reference));
+        memset(&bits, 0, sizeof(oggpack_buffer));
+
+        makeBitReader(unpackBookData, sizeof(unpackBookData), &buf, &ref,
+                      &bits);
+
+        ret = _vorbis_unpack_books(mVi, &bits);
+        if (!ret) {
+            ogg_packet pack;
+            memset(&pack, 0, sizeof(ogg_packet));
+            memset(&buf, 0, sizeof(ogg_buffer));
+            memset(&ref, 0, sizeof(ogg_reference));
+
+            vorbis_dsp_state *mState = new vorbis_dsp_state;
+            vorbis_dsp_init(mState, mVi);
+
+            buf.data = bufData;
+            buf.size = sizeof(bufData);
+            buf.refcount = REF_COUNT;
+
+            ref.buffer = &buf;
+            ref.length = buf.size;
+
+            pack.packet = &ref;
+            pack.bytes = ref.length;
+
+            vorbis_dsp_synthesis(mState, &pack, DECODE_PACKET);
+        }
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9536/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9536/poc.cpp
deleted file mode 100644
index 47d20e6..0000000
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9536/poc.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <dirent.h>
-#include <dlfcn.h>
-#include <signal.h>
-#include <string>
-#include <common.h>
-#include <FDK_bitbuffer.h>
-#define MAX_PATH_LENGTH 1035
-
-int main() {
-    FILE *fp;
-    char path[MAX_PATH_LENGTH];
-    void *libHandle;
-    static int (*real_FDK_getBitCnt)(HANDLE_FDK_BITBUF) = NULL;
-    fp = popen("find / -name libbluetooth.so 2>/dev/null ", "r");
-    if (fp == NULL) {
-        return EXIT_SUCCESS;
-    }
-    while (fgets(path, sizeof(path) - 1, fp) != NULL) {
-        path[strlen(path) - 1] = '\0'; /* remove \n */
-
-        libHandle = dlopen(path, RTLD_LAZY);
-        if (libHandle) {
-            real_FDK_getBitCnt = (int (*)(
-                    HANDLE_FDK_BITBUF))dlsym(libHandle, "FDK_getBitCnt");
-            dlclose(libHandle);
-            if (real_FDK_getBitCnt) {
-                pclose(fp);
-                /* The symbol of function is present, it means there is no fix patch */
-                return EXIT_VULNERABLE;
-            }
-        }
-    }
-    pclose(fp);
-    return EXIT_SUCCESS;
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
index c4ae6b5..c403fcf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -40,21 +40,21 @@
      * existing test methods
      ******************************************************************************/
 
+    /**
+     * b/112159345
+     * Vulnerability Behaviour: SIGSEGV in self
+     **/
+    @SecurityTest(minPatchLevel = "2018-01")
+    @Test
+    public void testPocCVE_2018_9527() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9527", null, getDevice());
+    }
 
     /******************************************************************************
      * To prevent merge conflicts, add tests for P below this comment, before any
      * existing test methods
      ******************************************************************************/
 
-    /**
-     * b/112662184
-     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
-     **/
-    @SecurityTest(minPatchLevel = "2018-11")
-    @Test
-    public void testPocCVE_2018_9536() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2018-9536", getDevice(), 60);
-    }
 
     /******************************************************************************
      * To prevent merge conflicts, add tests for Q below this comment, before any
diff --git a/hostsidetests/stagedinstall/Android.bp b/hostsidetests/stagedinstall/Android.bp
index 96ab887..75ea48e 100644
--- a/hostsidetests/stagedinstall/Android.bp
+++ b/hostsidetests/stagedinstall/Android.bp
@@ -62,6 +62,8 @@
         ":StagedInstallTestAppSamePackageNameAsApex",
         ":StagedInstallTestApexV2_SdkTargetP",
         ":StagedInstallTestCorruptedApex_b146895998",
+        ":StagedInstallTestApexV2_NoApkSignature",
+        ":StagedInstallTestApexV2_UnsignedPayload",
     ],
     static_libs: [
         "androidx.test.runner",
@@ -448,3 +450,43 @@
   filename: "corrupted_b146895998.apex",
   installable: false,
 }
+
+prebuilt_apex {
+  name: "StagedInstallTestApexV2_NoApkSignature",
+  arch: {
+        arm: {
+              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
+        },
+        arm64: {
+              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
+        },
+        x86: {
+              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
+        },
+        x86_64: {
+              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
+        },
+    },
+  filename: "com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
+  installable: false,
+}
+
+prebuilt_apex {
+  name: "StagedInstallTestApexV2_UnsignedPayload",
+  arch: {
+        arm: {
+              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex",
+        },
+        arm64: {
+              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex",
+        },
+        x86: {
+              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex",
+        },
+        x86_64: {
+              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex",
+        },
+    },
+  filename: "com.android.apex.cts.shim.v2_unsigned_payload.apex",
+  installable: false,
+}
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 c5c3a09..4f5b06c 100644
--- a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
@@ -147,6 +147,13 @@
             /*isApex*/true, "com.android.apex.cts.shim.v2_sdk_target_p.apex");
     private static final TestApp CorruptedApex_b146895998 = new TestApp(
             "StagedInstallTestCorruptedApex_b146895998", "", 1, true, "corrupted_b146895998.apex");
+    private static final TestApp Apex2NoApkSignature = new TestApp(
+            "StagedInstallTestApexV2_NoApkSignature", SHIM_PACKAGE_NAME, 1,
+            /*isApex*/true, "com.android.apex.cts.shim.v2_unsigned_apk_container.apex");
+    private static final TestApp Apex2UnsignedPayload = new TestApp(
+            "StagedInstallTestApexV2_UnsignedPayload", SHIM_PACKAGE_NAME, 1,
+            /*isApex*/true, "com.android.apex.cts.shim.v2_unsigned_payload.apex");
+
     @Before
     public void adoptShellPermissions() {
         InstrumentationRegistry
@@ -1070,6 +1077,27 @@
         assertThat(sessionInfo).isStagedSessionFailed();
     }
 
+    /**
+     * Should fail to pass apk signature check
+     */
+    @Test
+    public void testApexWithUnsignedApkFailsVerification() throws Exception {
+        assertThat(stageSingleApk(Apex2NoApkSignature).getErrorMessage())
+                .contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES");
+    }
+
+    /**
+     * Should fail to verify apex with unsigned payload
+     */
+    @Test
+    public void testApexWithUnsignedPayloadFailsVerification() throws Exception {
+        int sessionId = stageSingleApk(Apex2UnsignedPayload).assertSuccessful().getSessionId();
+        PackageInstaller.SessionInfo sessionInfo = waitForBroadcast(sessionId);
+        assertThat(sessionInfo).isStagedSessionFailed();
+        assertThat(sessionInfo.getStagedSessionErrorMessage())
+                .contains("AVB footer verification failed");
+    }
+
     private static long getInstalledVersion(String packageName) {
         Context context = InstrumentationRegistry.getInstrumentation().getContext();
         PackageManager pm = context.getPackageManager();
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 5054be4..91e83b2 100644
--- a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
@@ -537,6 +537,22 @@
         runPhase("testCorruptedApexFailsVerification_b146895998");
     }
 
+    /**
+     * Should fail to pass apk signature check
+     */
+    @Test
+    public void testApexWithUnsignedApkFailsVerification() throws Exception {
+        runPhase("testApexWithUnsignedApkFailsVerification");
+    }
+
+    /**
+     * Should fail to verify apex with unsigned payload
+     */
+    @Test
+    public void testApexWithUnsignedPayloadFailsVerification() throws Exception {
+        runPhase("testApexWithUnsignedPayloadFailsVerification");
+    }
+
     private boolean isUpdatingApexSupported() throws Exception {
         final String updatable = getDevice().getProperty("ro.apex.updatable");
         return updatable != null && updatable.equals("true");
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v1.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v1.apex
index 0a77a65..093770b 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v1.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v1.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2.apex
index 30f0e61..b45c93a 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex
index cdbd503..2c7fb51 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex
index b4a2d37..4829ab7 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
new file mode 100644
index 0000000..8f18159
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex
index 5970eb9..15c9ebf 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex
index 8300cd7..027cc9f 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex
index 99c1d2e..88f4355 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex
index 7c147ad..4b4bc9c 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex
index 3b0e8c3..db36942 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex
index 45480c1..94726c8 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
index e8bf987..59f3c88 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex
new file mode 100644
index 0000000..1187674
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex
new file mode 100644
index 0000000..f6f8719
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex
index 8b20f9d..d04bf00a 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
index 454002d..9b418a0 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex
index 8e64b73..cee12d8 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3.apex
index acf3be2..73320d5 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex
index b7a2d02..0358430 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex
index 07e3977..4b467f7 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v1.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v1.apex
index 0a6ec9b..085c1a9 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v1.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v1.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2.apex
index c9555a4..9ead68e 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex
index c6f6730..2c7fb51 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex
index cb40709..4829ab7 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
new file mode 100644
index 0000000..8f18159
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex
index 061f00d..15c9ebf 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex
index 89d687d..75efea3 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex
index c505cab..61e6bff 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex
index 961021f..4e28d6a 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex
index 482d3d8..a084b94 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex
index c461d9f..b8badc5 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
index cfdc9f0..0cced96 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex
new file mode 100644
index 0000000..5962142
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex
new file mode 100644
index 0000000..17f4d68
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex
index 9f22e23..d04bf00a 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
index 6300caf..9b418a0 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex
index 02dec8a..cee12d8 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3.apex
index 030e57d..03f1ecb 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex
index 3957085..3113f25 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex
index 017096e..8c911bb 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/arm/CtsShimTargetPSdk.apk b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/arm/CtsShimTargetPSdk.apk
index 065528c..5cd12d2 100644
--- a/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/arm/CtsShimTargetPSdk.apk
+++ b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/arm/CtsShimTargetPSdk.apk
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/x86/CtsShimTargetPSdk.apk b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/x86/CtsShimTargetPSdk.apk
index 065528c..5cd12d2 100644
--- a/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/x86/CtsShimTargetPSdk.apk
+++ b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/x86/CtsShimTargetPSdk.apk
Binary files differ
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index f2dc01c..5651690 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -1885,15 +1885,17 @@
         }
         // Base64 encoded proto com.android.service.nano.StringListParamProto,
         // which contains two strings "font_scale" and "screen_auto_brightness_adj".
-        final String ENCODED = "ChpzY3JlZW5fYXV0b19icmlnaHRuZXNzX2FkagoKZm9udF9zY2FsZQ";
-        final String FONT_SCALE = "font_scale";
+        final String encoded = "ChpzY3JlZW5fYXV0b19icmlnaHRuZXNzX2FkagoKZm9udF9zY2FsZQ";
+        final String font_scale = "font_scale";
         SettingSnapshot snapshot = null;
 
         // Set whitelist through device config.
         Thread.sleep(WAIT_TIME_SHORT);
         getDevice().executeShellCommand(
-                "device_config put settings_stats SystemFeature__float_whitelist " + ENCODED);
+                "device_config put settings_stats SystemFeature__float_whitelist " + encoded);
         Thread.sleep(WAIT_TIME_SHORT);
+        // Set font_scale value
+        getDevice().executeShellCommand("settings put system font_scale 1.5");
 
         // Get SettingSnapshot as a simple gauge metric.
         StatsdConfig.Builder config = createConfigBuilder();
@@ -1916,17 +1918,18 @@
         assertThat(atoms.size()).isAtLeast(2);
         for (Atom atom : atoms) {
             SettingSnapshot settingSnapshot = atom.getSettingSnapshot();
-            if (FONT_SCALE.equals(settingSnapshot.getName())) {
+            if (font_scale.equals(settingSnapshot.getName())) {
                 snapshot = settingSnapshot;
                 break;
             }
         }
-        // Get font_scale value.
-        final float fontScale = Float.parseFloat(
-                getDevice().executeShellCommand("settings get system font_scale"));
+
         Thread.sleep(WAIT_TIME_SHORT);
         // Test the data of atom.
         assertNotNull(snapshot);
+        // Get font_scale value and test value type.
+        final float fontScale = Float.parseFloat(
+                getDevice().executeShellCommand("settings get system font_scale"));
         assertThat(snapshot.getType()).isEqualTo(
                 SettingSnapshot.SettingsValueType.ASSIGNED_FLOAT_TYPE);
         assertThat(snapshot.getBoolValue()).isEqualTo(false);
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedDisplayTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedDisplayTest.java
index 721028a..0fd37c2 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedDisplayTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedDisplayTest.java
@@ -257,7 +257,7 @@
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
-            mActivityView = new ActivityView(this);
+            mActivityView = new ActivityView(this, null, 0, false, true);
             setContentView(mActivityView);
         }
 
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/DisplayUtils.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/DisplayUtils.java
index e11c60e..862b7b8 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/DisplayUtils.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/DisplayUtils.java
@@ -16,7 +16,7 @@
 
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
-import static android.view.Display.FLAG_PRIVATE;
+import static android.view.Display.DEFAULT_DISPLAY;
 
 import android.app.Activity;
 import android.content.Context;
@@ -29,7 +29,6 @@
 import android.util.DisplayMetrics;
 import android.view.Display;
 import android.view.Window;
-import android.view.WindowManager;
 
 import com.android.compatibility.common.util.TestUtils;
 
@@ -37,7 +36,7 @@
  * Utilities needed when interacting with the display
  */
 public class DisplayUtils {
-    private static final int DISPLAY_ADDED_TIMOUT_MS = 5000;
+    private static final int DISPLAY_ADDED_TIMEOUT_MS = 5000;
 
     public static int getStatusBarHeight(Activity activity) {
         final Rect rect = new Rect();
@@ -76,7 +75,11 @@
         }
 
         /**
-         * Creates a virtual display and waits until it's in display list.
+         * Creates a virtual display having same size with default display and waits until it's
+         * in display list. The density of the virtual display is based on
+         * {@link DisplayMetrics#xdpi} so that the threshold of gesture detection is same as
+         * the default display's.
+         *
          * @param context
          * @param isPrivate if this display is a private display.
          * @return virtual display.
@@ -110,17 +113,15 @@
                     Context.DISPLAY_SERVICE);
             displayManager.registerDisplayListener(listener, null);
 
-            final WindowManager windowManager = (WindowManager) context.getSystemService(
-                    Context.WINDOW_SERVICE);
             final DisplayMetrics metrics = new DisplayMetrics();
-            windowManager.getDefaultDisplay().getRealMetrics(metrics);
+            displayManager.getDisplay(DEFAULT_DISPLAY).getRealMetrics(metrics);
             final Display display = createDisplay(context, metrics.widthPixels,
-                    metrics.heightPixels, metrics.densityDpi, isPrivate);
+                    metrics.heightPixels, (int) metrics.xdpi, isPrivate);
 
             try {
                 TestUtils.waitOn(waitObject,
                         () -> displayManager.getDisplay(display.getDisplayId()) != null,
-                        DISPLAY_ADDED_TIMOUT_MS,
+                        DISPLAY_ADDED_TIMEOUT_MS,
                         String.format("wait for virtual display %d adding", display.getDisplayId()));
             } finally {
                 displayManager.unregisterDisplayListener(listener);
diff --git a/tests/app/Android.bp b/tests/app/Android.bp
index aaabca6..ed63def 100644
--- a/tests/app/Android.bp
+++ b/tests/app/Android.bp
@@ -81,6 +81,41 @@
 }
 
 android_test {
+    name: "CtsDownloadManagerInstaller",
+    defaults: ["cts_defaults"],
+    libs: [
+        "android.test.runner.stubs",
+        "org.apache.http.legacy",
+        "android.test.base.stubs",
+    ],
+    static_libs: [
+        "compatibility-device-util-axt",
+        "ctstestrunner-axt",
+        "ctstestserver",
+        "mockito-target-minus-junit4",
+        "androidx.test.rules",
+        "platform-test-annotations",
+        "androidx.test.rules",
+    ],
+    srcs: [
+        "DownloadManagerInstallerTest/src/**/*.java",
+        "src/android/app/cts/DownloadManagerTestBase.java",
+    ],
+    resource_dirs: ["app/res"],
+    asset_dirs: ["app/assets"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+    sdk_version: "test_current",
+    min_sdk_version: "14",
+    manifest: "DownloadManagerInstallerTest/AndroidManifest.xml",
+    test_config: "DownloadManagerInstallerTest/AndroidTest.xml",
+}
+
+android_test {
     name: "CtsAppExitTestCases",
     defaults: ["cts_defaults"],
     libs: [
diff --git a/tests/app/DownloadManagerInstallerTest/AndroidManifest.xml b/tests/app/DownloadManagerInstallerTest/AndroidManifest.xml
new file mode 100644
index 0000000..cb0b73b
--- /dev/null
+++ b/tests/app/DownloadManagerInstallerTest/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.app.cts.downloads.installer">
+
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+
+    <application android:usesCleartextTraffic="true"
+                 android:networkSecurityConfig="@xml/network_security_config">
+        <uses-library android:name="android.test.runner" />
+        <uses-library android:name="org.apache.http.legacy" android:required="false" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.app.cts.downloads.installer" />
+
+</manifest>
diff --git a/tests/app/DownloadManagerInstallerTest/AndroidTest.xml b/tests/app/DownloadManagerInstallerTest/AndroidTest.xml
new file mode 100644
index 0000000..51b26eb
--- /dev/null
+++ b/tests/app/DownloadManagerInstallerTest/AndroidTest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for DownloadManagerInstallerTest">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="framework" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsDownloadManagerInstaller.apk" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="appops set android.app.cts.downloads.installer REQUEST_INSTALL_PACKAGES allow" />
+        </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="package" value="android.app.cts.downloads.installer" />
+    </test>
+
+</configuration>
diff --git a/tests/app/DownloadManagerInstallerTest/src/android/app/cts/DownloadManagerInstallerTest.java b/tests/app/DownloadManagerInstallerTest/src/android/app/cts/DownloadManagerInstallerTest.java
new file mode 100644
index 0000000..5b9e0fe
--- /dev/null
+++ b/tests/app/DownloadManagerInstallerTest/src/android/app/cts/DownloadManagerInstallerTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.cts;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.DownloadManager;
+import android.content.IntentFilter;
+import android.net.Uri;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+@RunWith(AndroidJUnit4.class)
+public class DownloadManagerInstallerTest extends DownloadManagerTestBase {
+
+    @Test
+    public void testSetDestinationUri_otherAppObbDir() throws Exception {
+        File obbDir = mContext.getObbDir();
+
+        String otherAppObbPath = obbDir.getPath().replace(mContext.getPackageName(),
+                "android.app.cts.some_random_package");
+        File destPath = new File(otherAppObbPath);
+        destPath.mkdirs();
+
+        File destFile = new File(destPath, "test.obb");
+        deleteFromShell(destFile);
+
+        final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
+        try {
+            IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
+            mContext.registerReceiver(receiver, intentFilter);
+
+            DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl());
+            requestPublic.setDestinationUri(Uri.fromFile(destFile));
+            long id = mDownloadManager.enqueue(requestPublic);
+
+            int allDownloads = getTotalNumberDownloads();
+            assertEquals(1, allDownloads);
+
+            receiver.waitForDownloadComplete(SHORT_TIMEOUT, id);
+            assertSuccessfulDownload(id, destFile);
+
+            assertRemoveDownload(id, 0);
+        } finally {
+            mContext.unregisterReceiver(receiver);
+        }
+    }
+}
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index d8b9e2a..322069b 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -125,6 +125,7 @@
 import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -744,6 +745,7 @@
         ShortcutManager scManager =
                 (ShortcutManager) mContext.getSystemService(Context.SHORTCUT_SERVICE);
         scManager.removeAllDynamicShortcuts();
+        scManager.removeLongLivedShortcuts(Collections.singletonList(SHARE_SHORTCUT_ID));
     }
 
     /**
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
index 9bbc779..65df6fb 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
@@ -214,7 +214,8 @@
         public static final MockImeSessionRule sMockImeSessionRule = new MockImeSessionRule(
                 InstrumentationRegistry.getTargetContext(),
                 InstrumentationRegistry.getInstrumentation().getUiAutomation(),
-                new ImeSettings.Builder().setInlineSuggestionsEnabled(true));
+                new ImeSettings.Builder().setInlineSuggestionsEnabled(true)
+                        .setInlineSuggestionViewContentDesc(InlineUiBot.SUGGESTION_STRIP_DESC));
 
         protected static final RequiredFeatureRule sRequiredFeatureRule =
                 new RequiredFeatureRule(PackageManager.FEATURE_AUTOFILL);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
index b0747a5..f67bd5c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
@@ -1575,24 +1575,24 @@
     }
 
     @Test
-    public void testExplicitySaveButton() throws Exception {
-        explicitySaveButtonTest(false, 0);
+    public void testExplicitlySaveButton() throws Exception {
+        explicitlySaveButtonTest(false, 0);
     }
 
     @Test
-    public void testExplicitySaveButtonWhenAppClearFields() throws Exception {
-        explicitySaveButtonTest(true, 0);
+    public void testExplicitlySaveButtonWhenAppClearFields() throws Exception {
+        explicitlySaveButtonTest(true, 0);
     }
 
     @Test
-    public void testExplicitySaveButtonOnly() throws Exception {
-        explicitySaveButtonTest(false, SaveInfo.FLAG_DONT_SAVE_ON_FINISH);
+    public void testExplicitlySaveButtonOnly() throws Exception {
+        explicitlySaveButtonTest(false, SaveInfo.FLAG_DONT_SAVE_ON_FINISH);
     }
 
     /**
      * Tests scenario where service explicitly indicates which button is used to save.
      */
-    private void explicitySaveButtonTest(boolean clearFieldsOnSubmit, int flags) throws Exception {
+    private void explicitlySaveButtonTest(boolean clearFieldsOnSubmit, int flags) throws Exception {
         final boolean testBitmap = false;
         startActivity();
         mActivity.setAutoCommit(false);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineUiBot.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineUiBot.java
index 13f7ce8..1d1803a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineUiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineUiBot.java
@@ -33,11 +33,9 @@
 public final class InlineUiBot extends UiBot {
 
     private static final String TAG = "AutoFillInlineCtsUiBot";
-    //TODO: Change magic constant
-    private static final String RESOURCE_ID_SUGGESTION_STRIP = "message";
+    public static final String SUGGESTION_STRIP_DESC = "MockIme Inline Suggestion View";
 
-    private static final BySelector SUGGESTION_STRIP_SELECTOR =
-            By.res("android", RESOURCE_ID_SUGGESTION_STRIP);
+    private static final BySelector SUGGESTION_STRIP_SELECTOR = By.desc(SUGGESTION_STRIP_DESC);
 
     public InlineUiBot() {
         this(UI_TIMEOUT);
diff --git a/tests/framework/base/windowmanager/jetpack/Android.bp b/tests/framework/base/windowmanager/jetpack/Android.bp
new file mode 100644
index 0000000..860f63c
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/Android.bp
@@ -0,0 +1,52 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_library_import {
+    name: "cts_window-sidecar_nodeps",
+    aars: ["window-sidecar-release.aar"],
+    sdk_version: "current",
+}
+
+java_library {
+    name: "cts_window-sidecar",
+    sdk_version: "current",
+    static_libs: [
+        "cts_window-sidecar_nodeps",
+    ],
+    installable: false,
+}
+
+android_test {
+    name: "CtsWindowManagerJetpackTestCases",
+    defaults: ["cts_defaults"],
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "androidx.test.ext.junit",
+        "androidx.test.rules",
+        "compatibility-device-util-axt",
+        "platform-test-annotations",
+    ],
+    libs: [
+        "androidx.window.extensions",
+        "android.test.base.stubs",
+        "cts_window-sidecar",
+    ],
+    test_suites: [
+        "cts",
+        "vts",
+        "vts10",
+        "general-tests",
+    ],
+    sdk_version: "test_current",
+}
diff --git a/tests/framework/base/windowmanager/jetpack/AndroidManifest.xml b/tests/framework/base/windowmanager/jetpack/AndroidManifest.xml
new file mode 100644
index 0000000..a664f0b
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.server.wm.jetpack"
+          android:targetSandboxVersion="2">
+
+    <application android:label="CtsWindowManagerJetpackTestCases">
+        <uses-library android:name="android.test.runner" />
+        <uses-library android:name="androidx.window.extensions"
+                      android:required="false" />
+        <uses-library android:name="androidx.window.sidecar"
+                      android:required="false" />
+        <activity android:name="android.server.wm.jetpack.TestActivity" />
+        <activity android:name="android.server.wm.jetpack.TestConfigChangeHandlingActivity"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density|touchscreen"
+        />
+    </application>
+
+    <!--  self-instrumenting test package. -->
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:label="CTS tests of Jetpack Window Manager"
+        android:targetPackage="android.server.wm.jetpack" >
+    </instrumentation>
+</manifest>
diff --git a/tests/framework/base/windowmanager/jetpack/AndroidTest.xml b/tests/framework/base/windowmanager/jetpack/AndroidTest.xml
new file mode 100644
index 0000000..d4d2af2
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<configuration description="Config for CTS Jetpack WindowManager test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="framework"/>
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true"/>
+        <option name="test-file-name" value="CtsWindowManagerJetpackTestCases.apk"/>
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.server.wm.jetpack"/>
+    </test>
+</configuration>
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
new file mode 100644
index 0000000..4e67f8a
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionTest.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeFalse;
+
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
+import android.os.IBinder;
+import android.server.wm.jetpack.wrapper.TestDeviceState;
+import android.server.wm.jetpack.wrapper.TestDisplayFeature;
+import android.server.wm.jetpack.wrapper.TestInterfaceCompat;
+import android.server.wm.jetpack.wrapper.TestWindowLayoutInfo;
+
+import androidx.annotation.NonNull;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
+import androidx.test.rule.ActivityTestRule;
+
+import com.google.common.collect.BoundType;
+import com.google.common.collect.Range;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+/**
+ * Tests for the {@link androidx.window.extensions} implementation provided on the device (and only
+ * if one is available).
+ *
+ * Build/Install/Run:
+ *     atest CtsWindowManagerJetpackTestCases:ExtensionTest
+ */
+// TODO(b/155343832) add a foldable presubmit target.
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class ExtensionTest extends JetpackExtensionTestBase {
+    private ActivityTestRule<TestActivity> mActivityTestRule = new ActivityTestRule<>(
+            TestActivity.class, false /* initialTouchMode */, true /* launchActivity */);
+    private ActivityTestRule<TestConfigChangeHandlingActivity> mConfigHandlingActivityTestRule =
+            new ActivityTestRule<>(TestConfigChangeHandlingActivity.class,
+                    false /* initialTouchMode */, false /* launchActivity */);
+
+    /**
+     * This chain rule will launch TestActivity before each test starts, and cleanup both activities
+     * after each test finishes.
+     */
+    @Rule
+    public TestRule chain =
+            RuleChain.outerRule(mActivityTestRule).around(mConfigHandlingActivityTestRule);
+
+    private TestActivity mActivity;
+    private TestInterfaceCompat mExtension;
+    private IBinder mWindowToken;
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityTestRule.getActivity();
+        ExtensionUtils.assumeSupportedDevice(mActivity);
+
+        mExtension = ExtensionUtils.getInterfaceCompat(mActivity);
+        assertThat(mExtension).isNotNull();
+        mWindowToken = getActivityWindowToken(mActivity);
+        assertThat(mWindowToken).isNotNull();
+    }
+
+    @Test
+    public void testExtensionProvider_hasValidVersion() {
+        ExtensionUtils.assertValidVersion();
+    }
+
+    @Test
+    public void testExtensionInterface_setExtensionCallback() {
+        // Make sure that the method can be called without exception.
+        mExtension.setExtensionCallback(new TestInterfaceCompat.TestInterfaceCallback() {
+            @Override
+            public void onDeviceStateChanged(@NonNull TestDeviceState newDeviceState) {}
+
+            @Override
+            public void onWindowLayoutChanged(@NonNull IBinder windowToken,
+                    @NonNull TestWindowLayoutInfo newLayout) {}
+        });
+    }
+
+    @Test
+    public void testExtensionInterface_getWindowLayoutInfo() {
+        // No display feature to compare, finish test early.
+        assumeHasDisplayFeatures();
+
+        // Layout must happen after launch
+        assertThat(mActivity.waitForLayout()).isTrue();
+        TestWindowLayoutInfo windowLayoutInfo = mExtension.getWindowLayoutInfo(mWindowToken);
+        assertThat(windowLayoutInfo).isNotNull();
+
+        for (TestDisplayFeature displayFeature : windowLayoutInfo.getDisplayFeatures()) {
+            int featureType = displayFeature.getType();
+            assertThat(featureType).isAtLeast(TestDisplayFeature.TYPE_FOLD);
+            assertThat(featureType).isAtMost(TestDisplayFeature.TYPE_HINGE);
+
+            Rect featureRect = displayFeature.getBounds();
+            assertThat(featureRect.width() == 0 && featureRect.height() == 0).isFalse();
+            assertThat(featureRect.left).isAtLeast(0);
+            assertThat(featureRect.top).isAtLeast(0);
+            assertThat(featureRect.right).isAtLeast(0);
+            assertThat(featureRect.bottom).isAtLeast(0);
+            assertThat(featureRect.right).isAtMost(mActivity.getWidth());
+            assertThat(featureRect.bottom).isAtMost(mActivity.getHeight());
+        }
+    }
+
+    @Test
+    public void testExtensionInterface_onWindowLayoutChangeListenerAdded() {
+        // Make sure that the method can be called without exception.
+        mExtension.onWindowLayoutChangeListenerAdded(mWindowToken);
+    }
+
+    @Test
+    public void testExtensionInterface_onWindowLayoutChangeListenerRemoved() {
+        // Make sure that the method can be called without exception.
+        mExtension.onWindowLayoutChangeListenerRemoved(mWindowToken);
+    }
+
+    @Test
+    public void testExtensionInterface_getDeviceState() {
+        TestDeviceState deviceState = mExtension.getDeviceState();
+        assertThat(deviceState).isNotNull();
+
+        assertThat(deviceState.getPosture()).isIn(Range.range(
+                TestDeviceState.POSTURE_UNKNOWN, BoundType.CLOSED,
+                TestDeviceState.POSTURE_FLIPPED, BoundType.CLOSED));
+    }
+
+    @Test
+    public void testExtensionInterface_onDeviceStateListenersChanged() {
+        TestDeviceState deviceState1 = mExtension.getDeviceState();
+        mExtension.onDeviceStateListenersChanged(false /* isEmpty */);
+        TestDeviceState deviceState2 = mExtension.getDeviceState();
+        mExtension.onDeviceStateListenersChanged(true /* isEmpty */);
+        TestDeviceState deviceState3 = mExtension.getDeviceState();
+
+        assertThat(deviceState1).isEqualTo(deviceState2);
+        assertThat(deviceState1).isEqualTo(deviceState3);
+    }
+
+    @Test
+    public void testGetWindowLayoutInfo_configChanged_windowLayoutUpdates() {
+        // No display feature to compare, finish test early.
+        assumeHasDisplayFeatures();
+
+        TestConfigChangeHandlingActivity configHandlingActivity =
+                mConfigHandlingActivityTestRule.launchActivity(new Intent());
+        TestInterfaceCompat extension =
+                ExtensionUtils.getInterfaceCompat(configHandlingActivity);
+        assertThat(extension).isNotNull();
+        IBinder configHandlingActivityWindowToken = getActivityWindowToken(configHandlingActivity);
+        assertThat(configHandlingActivityWindowToken).isNotNull();
+
+        configHandlingActivity.resetLayoutCounter();
+        configHandlingActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+
+        configHandlingActivity.waitForLayout();
+        TestWindowLayoutInfo portraitWindowLayoutInfo =
+                extension.getWindowLayoutInfo(configHandlingActivityWindowToken);
+
+        configHandlingActivity.resetLayoutCounter();
+        configHandlingActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+
+        // Layout must happen after orientation change.
+        assertThat(configHandlingActivity.waitForLayout()).isTrue();
+        TestWindowLayoutInfo landscapeWindowLayoutInfo =
+                extension.getWindowLayoutInfo(configHandlingActivityWindowToken);
+
+        assertThat(portraitWindowLayoutInfo).isNotEqualTo(landscapeWindowLayoutInfo);
+    }
+
+    @Test
+    public void testGetWindowLayoutInfo_windowRecreated_windowLayoutUpdates() {
+        // No display feature to compare, finish test early.
+        assumeHasDisplayFeatures();
+
+        mActivity.resetLayoutCounter();
+        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+
+        mActivity.waitForLayout();
+        TestWindowLayoutInfo portraitWindowLayoutInfo =
+                mExtension.getWindowLayoutInfo(mWindowToken);
+
+        TestActivity.resetResumeCounter();
+        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+        TestActivity.waitForOnResume();
+
+        mWindowToken = getActivityWindowToken(mActivity);
+        assertThat(mWindowToken).isNotNull();
+
+        mActivity.waitForLayout();
+        TestWindowLayoutInfo landscapeWindowLayoutInfo =
+                mExtension.getWindowLayoutInfo(mWindowToken);
+
+        assertThat(portraitWindowLayoutInfo).isNotEqualTo(landscapeWindowLayoutInfo);
+    }
+
+    /** Skips devices that have no display feature to compare. */
+    private void assumeHasDisplayFeatures() {
+        TestWindowLayoutInfo windowLayoutInfo = mExtension.getWindowLayoutInfo(mWindowToken);
+        assertThat(windowLayoutInfo).isNotNull();
+        List<TestDisplayFeature> displayFeatures = windowLayoutInfo.getDisplayFeatures();
+        assumeFalse(displayFeatures == null || displayFeatures.isEmpty());
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionUtils.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionUtils.java
new file mode 100644
index 0000000..82b049e
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionUtils.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeFalse;
+
+import android.content.Context;
+import android.server.wm.jetpack.wrapper.extensionwrapperimpl.TestExtensionCompat;
+import android.server.wm.jetpack.wrapper.sidecarwrapperimpl.TestSidecarCompat;
+import android.server.wm.jetpack.wrapper.TestInterfaceCompat;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.window.extensions.ExtensionProvider;
+import androidx.window.sidecar.SidecarProvider;
+
+/** Helper class to get the vendor provided Extension/Sidecar implementation. */
+final class ExtensionUtils {
+    private static final String TAG = "TestInterfaceProvider";
+
+    /** Skips devices that don't implement the wm extension library. */
+    static void assumeSupportedDevice(Context context) {
+        assumeFalse(TextUtils.isEmpty(getVersion()) && getInterfaceCompat(context) == null);
+    }
+
+    /** Asserts that the vendor provided version is in the correct format and range. */
+    static void assertValidVersion() {
+        if (getExtensionVersion() != null) {
+            String versionStr = getExtensionVersion();
+            assertThat(Version.isValidVersion(versionStr)).isTrue();
+            assertThat(Version.parse(versionStr)).isAtLeast(Version.VERSION_1_0);
+        } else if (getSidecarVersion() != null) {
+            String versionStr = getSidecarVersion();
+            assertThat(Version.isValidVersion(versionStr)).isTrue();
+            assertThat(Version.parse(versionStr)).isEqualTo(Version.VERSION_0_1);
+        }
+    }
+
+    /**
+     * Gets the vendor provided Extension implementation if available. If not available, gets the
+     * Sidecar implementation (deprecated). If neither is available, returns {@code null}.
+     */
+    @Nullable
+    static TestInterfaceCompat getInterfaceCompat(Context context) {
+        if (!TextUtils.isEmpty(getExtensionVersion())) {
+            return getExtensionInterfaceCompat(context);
+        } else if (!TextUtils.isEmpty(getSidecarVersion())) {
+            return getSidecarInterfaceCompat(context);
+        }
+        return null;
+    }
+
+    @Nullable
+    private static String getVersion() {
+        if (!TextUtils.isEmpty(getExtensionVersion())) {
+            return getExtensionVersion();
+        } else if (!TextUtils.isEmpty(getSidecarVersion())) {
+            return getSidecarVersion();
+        }
+        return null;
+    }
+
+    @Nullable
+    private static String getExtensionVersion() {
+        try {
+            return ExtensionProvider.getApiVersion();
+        } catch (NoClassDefFoundError e) {
+            Log.d(TAG, "Extension version not found");
+            return null;
+        } catch (UnsupportedOperationException e) {
+            Log.d(TAG, "Stub Extension");
+            return null;
+        }
+    }
+
+    @Nullable
+    private static TestExtensionCompat getExtensionInterfaceCompat(Context context) {
+        try {
+            return TestExtensionCompat.create(ExtensionProvider.getExtensionImpl(context));
+        } catch (NoClassDefFoundError e) {
+            Log.d(TAG, "Extension implementation not found");
+            return null;
+        } catch (UnsupportedOperationException e) {
+            Log.d(TAG, "Stub Extension");
+            return null;
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    @Nullable
+    private static String getSidecarVersion() {
+        try {
+            return SidecarProvider.getApiVersion();
+        } catch (NoClassDefFoundError e) {
+            Log.d(TAG, "Sidecar version not found");
+            return null;
+        } catch (UnsupportedOperationException e) {
+            Log.d(TAG, "Stub Sidecar");
+            return null;
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    @Nullable
+    private static TestSidecarCompat getSidecarInterfaceCompat(Context context) {
+        try {
+            return TestSidecarCompat.create(SidecarProvider.getSidecarImpl(context));
+        } catch (NoClassDefFoundError e) {
+            Log.d(TAG, "Sidecar implementation not found");
+            return null;
+        } catch (UnsupportedOperationException e) {
+            Log.d(TAG, "Stub Sidecar");
+            return null;
+        }
+    }
+
+    private ExtensionUtils() {}
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/JetpackExtensionTestBase.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/JetpackExtensionTestBase.java
new file mode 100644
index 0000000..d460241
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/JetpackExtensionTestBase.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack;
+
+import android.app.Activity;
+import android.os.IBinder;
+
+/** Base class for all tests in the module. Copied from androidx.window.WindowTestBase. */
+class JetpackExtensionTestBase {
+    static IBinder getActivityWindowToken(Activity activity) {
+        return activity.getWindow().getAttributes().token;
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/TestActivity.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/TestActivity.java
new file mode 100644
index 0000000..44f5306
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/TestActivity.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test activity that can verify whether the layout changes. Copied from
+ * androidx.window.TestActivity.
+ */
+public class TestActivity extends Activity implements View.OnLayoutChangeListener {
+
+    private int mRootViewId;
+    private CountDownLatch mLayoutLatch;
+    private static CountDownLatch sResumeLatch = new CountDownLatch(1);
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final View contentView = new View(this);
+        mRootViewId = View.generateViewId();
+        contentView.setId(mRootViewId);
+        setContentView(contentView);
+
+        resetLayoutCounter();
+        getWindow().getDecorView().addOnLayoutChangeListener(this);
+    }
+
+    int getWidth() {
+        return findViewById(mRootViewId).getWidth();
+    }
+
+    int getHeight() {
+        return findViewById(mRootViewId).getHeight();
+    }
+
+    @Override
+    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
+            int oldTop, int oldRight, int oldBottom) {
+        mLayoutLatch.countDown();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        sResumeLatch.countDown();
+    }
+
+    /**
+     * Resets layout counter when waiting for a layout to happen before calling
+     * {@link #waitForLayout()}.
+     */
+    void resetLayoutCounter() {
+        mLayoutLatch = new CountDownLatch(1);
+    }
+
+    /**
+     * Blocks and waits for the next layout to happen. {@link #resetLayoutCounter()} must be called
+     * before calling this method.
+     * @return {@code true} if the layout happened before the timeout count reached zero and
+     *         {@code false} if the waiting time elapsed before the layout happened.
+     */
+    boolean waitForLayout() {
+        try {
+            return mLayoutLatch.await(3, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Resets layout counter when waiting for a layout to happen before calling
+     * {@link #waitForOnResume()}.
+     */
+    static void resetResumeCounter() {
+        sResumeLatch = new CountDownLatch(1);
+    }
+
+    /**
+     * Same as {@link #waitForLayout()}, but waits for onResume() to be called for any activity of
+     * this class. This can be used to track activity re-creation.
+     * @return {@code true} if the onResume() happened before the timeout count reached zero and
+     *         {@code false} if the waiting time elapsed before the onResume() happened.
+     */
+    static boolean waitForOnResume() {
+        try {
+            return sResumeLatch.await(3, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            return false;
+        }
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/TestConfigChangeHandlingActivity.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/TestConfigChangeHandlingActivity.java
new file mode 100644
index 0000000..37b163a
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/TestConfigChangeHandlingActivity.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack;
+
+/**
+ * Activity that handles orientation configuration change. Copied from
+ * androidx.window.TestConfigChangeHandlingActivity.
+ */
+public final class TestConfigChangeHandlingActivity extends TestActivity {
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/Version.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/Version.java
new file mode 100644
index 0000000..a9978c0
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/Version.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack;
+
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.math.BigInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * Class encapsulating a version with major, minor, patch and description values. Copied from
+ * androidx.window.Version.
+ */
+final class Version implements Comparable<Version> {
+    static final Version UNKNOWN = new Version(0, 0, 0, "");
+    static final Version VERSION_0_1 = new Version(0, 1, 0, "");
+    static final Version VERSION_1_0 = new Version(1, 0, 0, "");
+    static final Version CURRENT = VERSION_1_0;
+
+    private static final String VERSION_PATTERN_STRING =
+            "(\\d+)(?:\\.(\\d+))(?:\\.(\\d+))(?:-(.+))?";
+
+    private final int mMajor;
+    private final int mMinor;
+    private final int mPatch;
+    private final String mDescription;
+    // Cached BigInteger value of the version.
+    private BigInteger mBigInteger;
+
+    private Version(int major, int minor, int patch, String description) {
+        mMajor = major;
+        mMinor = minor;
+        mPatch = patch;
+        mDescription = description;
+    }
+
+    /**
+     * Parses a string to a version object.
+     *
+     * @param versionString string in the format "1.2.3" or "1.2.3-Description"
+     *                      (major.minor.patch[-description])
+     * @return the parsed Version object or {@code null}> if the versionString format is invalid.
+     */
+    @Nullable
+    static Version parse(String versionString) {
+        if (TextUtils.isEmpty(versionString)) {
+            return null;
+        }
+
+        Matcher matcher = Pattern.compile(VERSION_PATTERN_STRING).matcher(versionString);
+        if (!matcher.matches()) {
+            return null;
+        }
+
+        int major = Integer.parseInt(matcher.group(1));
+        int minor = Integer.parseInt(matcher.group(2));
+        int patch = Integer.parseInt(matcher.group(3));
+        String description = matcher.group(4) != null ? matcher.group(4) : "";
+        return new Version(major, minor, patch, description);
+    }
+
+    /** Checks whether the version is in the correct format. */
+    static boolean isValidVersion(String versionString) {
+        Matcher matcher = Pattern.compile(VERSION_PATTERN_STRING).matcher(versionString);
+        return matcher.matches();
+    }
+
+    int getMajor() {
+        return mMajor;
+    }
+
+    int getMinor() {
+        return mMinor;
+    }
+
+    int getPatch() {
+        return mPatch;
+    }
+
+    String getDescription() {
+        return mDescription;
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder(getMajor())
+                .append(".")
+                .append(getMinor())
+                .append(".")
+                .append(getPatch());
+        if (!TextUtils.isEmpty(getDescription())) {
+            sb.append("-").append(getDescription());
+        }
+        return sb.toString();
+    }
+
+    /**
+     * To compare the major, minor and patch version with another.
+     *
+     * @param other The version to compare to this one.
+     * @return 0 if it have the same major minor and patch version; less than 0 if this version
+     * sorts ahead of <var>other</var>; greater than 0 if this version sorts after <var>other</var>.
+     */
+    @Override
+    public int compareTo(@NonNull Version other) {
+        return toBigInteger().compareTo(other.toBigInteger());
+    }
+
+    @NonNull
+    private BigInteger toBigInteger() {
+        if (mBigInteger == null) {
+            mBigInteger = BigInteger.valueOf(mMajor)
+                    .shiftLeft(32)
+                    .or(BigInteger.valueOf(mMinor))
+                    .shiftLeft(32)
+                    .or(BigInteger.valueOf(mPatch));
+        }
+        return mBigInteger;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof Version)) {
+            return false;
+        }
+
+        Version otherVersionObj = (Version) obj;
+
+        // The equals checking ignores the description.
+        return mMajor == otherVersionObj.mMajor
+                && mMinor == otherVersionObj.mMinor
+                && mPatch == otherVersionObj.mPatch;
+    }
+
+    @Override
+    public int hashCode() {
+        // The hash code ignores the description.
+        int result = 17;
+        result = result * 31 + mMajor;
+        result = result * 31 + mMinor;
+        result = result * 31 + mPatch;
+        return result;
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestDeviceState.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestDeviceState.java
new file mode 100644
index 0000000..499b4da
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestDeviceState.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Test interface for {@link androidx.window.extensions.ExtensionDeviceState} and
+ * {@link androidx.window.sidecar.SidecarDeviceState} that serves as an API compatibility wrapper.
+ *
+ * @see android.server.wm.jetpack.wrapper.extensionwrapperimpl.TestExtensionDeviceState
+ * @see android.server.wm.jetpack.wrapper.sidecarwrapperimpl.TestSidecarDeviceState
+ */
+public interface TestDeviceState {
+
+    /** Copied from {@link androidx.window.extensions.ExtensionDeviceState}. */
+    public static final int POSTURE_UNKNOWN = 0;
+    public static final int POSTURE_CLOSED = 1;
+    public static final int POSTURE_HALF_OPENED = 2;
+    public static final int POSTURE_OPENED = 3;
+    public static final int POSTURE_FLIPPED = 4;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            POSTURE_UNKNOWN,
+            POSTURE_CLOSED,
+            POSTURE_HALF_OPENED,
+            POSTURE_OPENED,
+            POSTURE_FLIPPED
+    })
+    @interface Posture{}
+
+    /** Gets the current posture of the foldable device. */
+    @Posture
+    int getPosture();
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestDisplayFeature.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestDisplayFeature.java
new file mode 100644
index 0000000..8eb0774
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestDisplayFeature.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper;
+
+import android.graphics.Rect;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Test interface for {@link androidx.window.extensions.ExtensionDisplayFeature} and
+ * {@link androidx.window.sidecar.SidecarDisplayFeature} that serves as an API compatibility
+ * wrapper.
+ *
+ * @see android.server.wm.jetpack.wrapper.extensionwrapperimpl.TestExtensionDisplayFeature
+ * @see android.server.wm.jetpack.wrapper.sidecarwrapperimpl.TestSidecarDisplayFeature
+ */
+public interface TestDisplayFeature {
+
+    /**
+     * A fold in the flexible screen without a physical gap.
+     */
+    public static final int TYPE_FOLD = 1;
+
+    /**
+     * A physical separation with a hinge that allows two display panels to fold.
+     */
+    public static final int TYPE_HINGE = 2;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            TYPE_FOLD,
+            TYPE_HINGE,
+    })
+    @interface Type{}
+
+    /** Gets the bounding rect of the display feature in window coordinate space. */
+    Rect getBounds();
+
+    /** Gets the type of the display feature. */
+    int getType();
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestInterfaceCompat.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestInterfaceCompat.java
new file mode 100644
index 0000000..749d8c5
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestInterfaceCompat.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper;
+
+import android.os.IBinder;
+import android.server.wm.jetpack.wrapper.extensionwrapperimpl.TestExtensionCompat;
+import android.server.wm.jetpack.wrapper.sidecarwrapperimpl.TestSidecarCompat;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Test interface for {@link androidx.window.extensions.ExtensionInterface} and
+ * {@link androidx.window.sidecar.SidecarInterface} that serves as an API compatibility wrapper.
+ *
+ * @see TestExtensionCompat
+ * @see TestSidecarCompat
+ */
+public interface TestInterfaceCompat {
+
+    /**
+     * Registers the support library as the callback for the extension. This interface will be used
+     * to report all extension changes to the support library.
+     */
+    void setExtensionCallback(@NonNull TestInterfaceCallback callback);
+
+    /**
+     * Gets current information about the display features present within the application window.
+     */
+    TestWindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken);
+
+    /**
+     * Notifies extension that a listener for display feature layout changes was registered for the
+     * given window token.
+     */
+    void onWindowLayoutChangeListenerAdded(@NonNull IBinder windowToken);
+
+    /**
+     * Notifies extension that a listener for display feature layout changes was removed for the
+     * given window token.
+     */
+    void onWindowLayoutChangeListenerRemoved(@NonNull IBinder windowToken);
+
+    /**
+     * Gets current device state.
+     * @see #onDeviceStateListenersChanged(boolean)
+     */
+    TestDeviceState getDeviceState();
+
+    /**
+     * Notifies the extension that a device state change listener was updated.
+     * @param isEmpty flag indicating if the list of device state change listeners is empty.
+     */
+    void onDeviceStateListenersChanged(boolean isEmpty);
+
+    /**
+     * Callback that will be registered with the WindowManager library, and that the extension
+     * should use to report all state changes.
+     */
+    interface TestInterfaceCallback {
+        /**
+         * Called by extension when the device state changes.
+         */
+        void onDeviceStateChanged(@NonNull TestDeviceState newDeviceState);
+
+        /**
+         * Called by extension when the feature layout inside the window changes.
+         */
+        void onWindowLayoutChanged(@NonNull IBinder windowToken,
+                @NonNull TestWindowLayoutInfo newLayout);
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestWindowLayoutInfo.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestWindowLayoutInfo.java
new file mode 100644
index 0000000..5e4621d
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/TestWindowLayoutInfo.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper;
+
+import androidx.annotation.Nullable;
+
+import java.util.List;
+
+/**
+ * Test interface for {@link androidx.window.extensions.ExtensionWindowLayoutInfo} and
+ * {@link androidx.window.sidecar.SidecarWindowLayoutInfo} that serves as an API compatibility
+ * wrapper.
+ *
+ * @see android.server.wm.jetpack.wrapper.extensionwrapperimpl.TestExtensionWindowLayoutInfo
+ * @see android.server.wm.jetpack.wrapper.sidecarwrapperimpl.TestSidecarWindowLayoutInfo
+ */
+public interface TestWindowLayoutInfo {
+    /** Gets the list of display features present within the window. */
+    @Nullable
+    List<TestDisplayFeature> getDisplayFeatures();
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionCompat.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionCompat.java
new file mode 100644
index 0000000..3f4d72d
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionCompat.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper.extensionwrapperimpl;
+
+import android.os.IBinder;
+import android.server.wm.jetpack.wrapper.TestDeviceState;
+import android.server.wm.jetpack.wrapper.TestInterfaceCompat;
+import android.server.wm.jetpack.wrapper.TestWindowLayoutInfo;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.extensions.ExtensionDeviceState;
+import androidx.window.extensions.ExtensionInterface;
+import androidx.window.extensions.ExtensionWindowLayoutInfo;
+
+/** Compatibility wrapper for extension versions v1.0+. */
+public final class TestExtensionCompat implements TestInterfaceCompat {
+
+    @Nullable
+    public static TestExtensionCompat create(@Nullable ExtensionInterface extensionInterface) {
+        return extensionInterface == null ? null : new TestExtensionCompat(extensionInterface);
+    }
+
+    @NonNull
+    private final ExtensionInterface mExtensionInterface;
+
+    private TestExtensionCompat(@NonNull ExtensionInterface extensionInterface) {
+        mExtensionInterface = extensionInterface;
+    }
+
+    @Override
+    public void setExtensionCallback(@NonNull TestInterfaceCallback callback) {
+        mExtensionInterface.setExtensionCallback(new ExtensionInterface.ExtensionCallback() {
+            @Override
+            public void onDeviceStateChanged(@NonNull ExtensionDeviceState newDeviceState) {
+                callback.onDeviceStateChanged(TestExtensionDeviceState.create(newDeviceState));
+            }
+
+            @Override
+            public void onWindowLayoutChanged(@NonNull IBinder windowToken,
+                    @NonNull ExtensionWindowLayoutInfo newLayout) {
+                callback.onWindowLayoutChanged(
+                        windowToken,
+                        TestExtensionWindowLayoutInfo.create(newLayout));
+            }
+        });
+    }
+
+    @Override
+    public TestWindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken) {
+        return TestExtensionWindowLayoutInfo.create(
+                mExtensionInterface.getWindowLayoutInfo(windowToken));
+    }
+
+    @Override
+    public void onWindowLayoutChangeListenerAdded(@NonNull IBinder windowToken) {
+        mExtensionInterface.onWindowLayoutChangeListenerAdded(windowToken);
+    }
+
+    @Override
+    public void onWindowLayoutChangeListenerRemoved(@NonNull IBinder windowToken) {
+        mExtensionInterface.onWindowLayoutChangeListenerRemoved(windowToken);
+    }
+
+    @Override
+    public TestDeviceState getDeviceState() {
+        return TestExtensionDeviceState.create(mExtensionInterface.getDeviceState());
+    }
+
+    @Override
+    public void onDeviceStateListenersChanged(boolean isEmpty) {
+        mExtensionInterface.onDeviceStateListenersChanged(isEmpty);
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionDeviceState.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionDeviceState.java
new file mode 100644
index 0000000..60362b4
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionDeviceState.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper.extensionwrapperimpl;
+
+import android.server.wm.jetpack.wrapper.TestDeviceState;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.extensions.ExtensionDeviceState;
+
+import com.google.common.base.Preconditions;
+
+/** Compatibility wrapper for extension versions v1.0+. */
+final class TestExtensionDeviceState implements TestDeviceState {
+
+    @Nullable
+    static TestExtensionDeviceState create(@Nullable ExtensionDeviceState extensionDeviceState) {
+        return extensionDeviceState == null
+                ? null
+                : new TestExtensionDeviceState(extensionDeviceState);
+    }
+
+    private final ExtensionDeviceState mExtensionDeviceState;
+
+    private TestExtensionDeviceState(@NonNull ExtensionDeviceState extensionDeviceState) {
+        mExtensionDeviceState = Preconditions.checkNotNull(extensionDeviceState);
+    }
+
+    @Override
+    public int getPosture() {
+        return mExtensionDeviceState.getPosture();
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return mExtensionDeviceState.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof TestExtensionDeviceState)) {
+            return false;
+        }
+        final TestExtensionDeviceState other = (TestExtensionDeviceState) obj;
+        return mExtensionDeviceState.equals(other.mExtensionDeviceState);
+    }
+
+    @Override
+    public int hashCode() {
+        return mExtensionDeviceState.hashCode();
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionDisplayFeature.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionDisplayFeature.java
new file mode 100644
index 0000000..abc7d4d
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionDisplayFeature.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper.extensionwrapperimpl;
+
+import android.graphics.Rect;
+import android.server.wm.jetpack.wrapper.TestDisplayFeature;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.extensions.ExtensionDisplayFeature;
+
+/** Compatibility wrapper for extension versions v1.0+. */
+final class TestExtensionDisplayFeature implements TestDisplayFeature {
+
+    @Nullable
+    static TestExtensionDisplayFeature create(
+            @Nullable ExtensionDisplayFeature extensionDisplayFeature) {
+        return extensionDisplayFeature == null
+                ? null
+                : new TestExtensionDisplayFeature(extensionDisplayFeature);
+    }
+
+    private final ExtensionDisplayFeature mExtensionDisplayFeature;
+
+    private TestExtensionDisplayFeature(@NonNull ExtensionDisplayFeature extensionDisplayFeature) {
+        mExtensionDisplayFeature = extensionDisplayFeature;
+    }
+
+    @Override
+    public Rect getBounds() {
+        return mExtensionDisplayFeature.getBounds();
+    }
+
+    @Override
+    public int getType() {
+        return mExtensionDisplayFeature.getType();
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return mExtensionDisplayFeature.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof TestExtensionDisplayFeature)) {
+            return false;
+        }
+        final TestExtensionDisplayFeature other = (TestExtensionDisplayFeature) obj;
+        return mExtensionDisplayFeature.equals(other.mExtensionDisplayFeature);
+    }
+
+    @Override
+    public int hashCode() {
+        return mExtensionDisplayFeature.hashCode();
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionWindowLayoutInfo.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionWindowLayoutInfo.java
new file mode 100644
index 0000000..e31a29d
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/extensionwrapperimpl/TestExtensionWindowLayoutInfo.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper.extensionwrapperimpl;
+
+
+import android.server.wm.jetpack.wrapper.TestDisplayFeature;
+import android.server.wm.jetpack.wrapper.TestWindowLayoutInfo;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.extensions.ExtensionDisplayFeature;
+import androidx.window.extensions.ExtensionWindowLayoutInfo;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/** Compatibility wrapper for extension versions v1.0+. */
+final class TestExtensionWindowLayoutInfo implements TestWindowLayoutInfo {
+
+    @Nullable
+    static TestExtensionWindowLayoutInfo create(
+            @Nullable ExtensionWindowLayoutInfo extensionWindowLayoutInfo) {
+        return extensionWindowLayoutInfo == null
+                ? null
+                : new TestExtensionWindowLayoutInfo(extensionWindowLayoutInfo);
+    }
+
+    private final ExtensionWindowLayoutInfo mExtensionWindowLayoutInfo;
+
+    private TestExtensionWindowLayoutInfo(ExtensionWindowLayoutInfo extensionWindowLayoutInfo) {
+        mExtensionWindowLayoutInfo = extensionWindowLayoutInfo;
+    }
+
+    @Nullable
+    @Override
+    public List<TestDisplayFeature> getDisplayFeatures() {
+        List<ExtensionDisplayFeature> displayFeatures =
+                mExtensionWindowLayoutInfo.getDisplayFeatures();
+        return displayFeatures == null
+                ? null
+                : mExtensionWindowLayoutInfo.getDisplayFeatures()
+                        .stream()
+                        .map(TestExtensionDisplayFeature::create)
+                        .collect(Collectors.toList());
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return mExtensionWindowLayoutInfo.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof TestExtensionWindowLayoutInfo)) {
+            return false;
+        }
+        final TestExtensionWindowLayoutInfo other = (TestExtensionWindowLayoutInfo) obj;
+        return mExtensionWindowLayoutInfo.equals(other.mExtensionWindowLayoutInfo);
+    }
+
+    @Override
+    public int hashCode() {
+        return mExtensionWindowLayoutInfo.hashCode();
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarCompat.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarCompat.java
new file mode 100644
index 0000000..47b09e2
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarCompat.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper.sidecarwrapperimpl;
+
+import android.os.IBinder;
+import android.server.wm.jetpack.wrapper.TestDeviceState;
+import android.server.wm.jetpack.wrapper.TestInterfaceCompat;
+import android.server.wm.jetpack.wrapper.TestWindowLayoutInfo;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.sidecar.SidecarDeviceState;
+import androidx.window.sidecar.SidecarInterface;
+import androidx.window.sidecar.SidecarWindowLayoutInfo;
+
+/** Extension interface compatibility wrapper for v0.1 sidecar. */
+@SuppressWarnings("deprecation")
+public final class TestSidecarCompat implements TestInterfaceCompat {
+
+    @Nullable
+    public static TestSidecarCompat create(@Nullable SidecarInterface sidecarInterface) {
+        return sidecarInterface == null ? null : new TestSidecarCompat(sidecarInterface);
+    }
+
+    @NonNull
+    private final SidecarInterface mSidecarInterface;
+
+    private TestSidecarCompat(@NonNull SidecarInterface sidecarInterface) {
+        mSidecarInterface = sidecarInterface;
+    }
+
+    @Override
+    public void setExtensionCallback(@NonNull TestInterfaceCallback callback) {
+        mSidecarInterface.setSidecarCallback(new SidecarInterface.SidecarCallback() {
+            @Override
+            public void onDeviceStateChanged(@NonNull SidecarDeviceState newDeviceState) {
+                callback.onDeviceStateChanged(TestSidecarDeviceState.create(newDeviceState));
+            }
+
+            @Override
+            public void onWindowLayoutChanged(@NonNull IBinder windowToken,
+                    @NonNull SidecarWindowLayoutInfo newLayout) {
+                callback.onWindowLayoutChanged(
+                        windowToken,
+                        TestSidecarWindowLayoutInfo.create(newLayout));
+            }
+        });
+    }
+
+    @Override
+    public TestWindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken) {
+        return TestSidecarWindowLayoutInfo.create(
+                mSidecarInterface.getWindowLayoutInfo(windowToken));
+    }
+
+    @Override
+    public void onWindowLayoutChangeListenerAdded(@NonNull IBinder windowToken) {
+        mSidecarInterface.onWindowLayoutChangeListenerAdded(windowToken);
+    }
+
+    @Override
+    public void onWindowLayoutChangeListenerRemoved(@NonNull IBinder windowToken) {
+        mSidecarInterface.onWindowLayoutChangeListenerRemoved(windowToken);
+    }
+
+    @Override
+    public TestDeviceState getDeviceState() {
+        return TestSidecarDeviceState.create(mSidecarInterface.getDeviceState());
+    }
+
+    @Override
+    public void onDeviceStateListenersChanged(boolean isEmpty) {
+        mSidecarInterface.onDeviceStateListenersChanged(isEmpty);
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarDeviceState.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarDeviceState.java
new file mode 100644
index 0000000..63a2a44
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarDeviceState.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper.sidecarwrapperimpl;
+
+import android.server.wm.jetpack.wrapper.TestDeviceState;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.sidecar.SidecarDeviceState;
+
+/** Extension interface compatibility wrapper for v0.1 sidecar. */
+@SuppressWarnings("deprecation")
+final class TestSidecarDeviceState implements TestDeviceState {
+
+    @Nullable
+    static TestSidecarDeviceState create(@Nullable SidecarDeviceState sidecarDeviceState) {
+        return sidecarDeviceState == null
+                ? null
+                : new TestSidecarDeviceState(sidecarDeviceState);
+    }
+
+    private final SidecarDeviceState mSidecarDeviceState;
+
+    private TestSidecarDeviceState(@NonNull SidecarDeviceState sidecarDeviceState) {
+        mSidecarDeviceState = sidecarDeviceState;
+    }
+
+    @Override
+    public int getPosture() {
+        return mSidecarDeviceState.posture;
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return mSidecarDeviceState.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof TestSidecarDeviceState)) {
+            return false;
+        }
+        final TestSidecarDeviceState other = (TestSidecarDeviceState) obj;
+        return mSidecarDeviceState.equals(other.mSidecarDeviceState);
+    }
+
+    @Override
+    public int hashCode() {
+        return mSidecarDeviceState.hashCode();
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarDisplayFeature.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarDisplayFeature.java
new file mode 100644
index 0000000..e94d15d
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarDisplayFeature.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper.sidecarwrapperimpl;
+
+import android.graphics.Rect;
+import android.server.wm.jetpack.wrapper.TestDisplayFeature;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.sidecar.SidecarDisplayFeature;
+
+/** Extension interface compatibility wrapper for v0.1 sidecar. */
+@SuppressWarnings("deprecation")
+final class TestSidecarDisplayFeature implements TestDisplayFeature {
+
+    @Nullable
+    static TestSidecarDisplayFeature create(@Nullable SidecarDisplayFeature sidecarDisplayFeature) {
+        return sidecarDisplayFeature == null
+                ? null
+                : new TestSidecarDisplayFeature(sidecarDisplayFeature);
+    }
+
+    private final SidecarDisplayFeature mSidecarDisplayFeature;
+
+    private TestSidecarDisplayFeature(@NonNull SidecarDisplayFeature sidecarDisplayFeature) {
+        mSidecarDisplayFeature = sidecarDisplayFeature;
+    }
+
+    @Override
+    public Rect getBounds() {
+        return mSidecarDisplayFeature.getRect();
+    }
+
+    @Override
+    public int getType() {
+        return mSidecarDisplayFeature.getType();
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return mSidecarDisplayFeature.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof TestSidecarDisplayFeature)) {
+            return false;
+        }
+        final TestSidecarDisplayFeature other = (TestSidecarDisplayFeature) obj;
+        return mSidecarDisplayFeature.equals(other.mSidecarDisplayFeature);
+    }
+
+    @Override
+    public int hashCode() {
+        return mSidecarDisplayFeature.hashCode();
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarWindowLayoutInfo.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarWindowLayoutInfo.java
new file mode 100644
index 0000000..163e0b6
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/wrapper/sidecarwrapperimpl/TestSidecarWindowLayoutInfo.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.wrapper.sidecarwrapperimpl;
+
+
+import android.server.wm.jetpack.wrapper.TestDisplayFeature;
+import android.server.wm.jetpack.wrapper.TestWindowLayoutInfo;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.sidecar.SidecarDisplayFeature;
+import androidx.window.sidecar.SidecarWindowLayoutInfo;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/** Extension interface compatibility wrapper for v0.1 sidecar. */
+@SuppressWarnings("deprecation")
+final class TestSidecarWindowLayoutInfo implements TestWindowLayoutInfo {
+
+    @Nullable
+    static TestSidecarWindowLayoutInfo create(
+            @Nullable SidecarWindowLayoutInfo sidecarWindowLayoutInfo) {
+        return sidecarWindowLayoutInfo == null
+                ? null
+                : new TestSidecarWindowLayoutInfo(sidecarWindowLayoutInfo);
+    }
+
+    private final SidecarWindowLayoutInfo mSidecarWindowLayoutInfo;
+
+    private TestSidecarWindowLayoutInfo(SidecarWindowLayoutInfo sidecarWindowLayoutInfo) {
+        mSidecarWindowLayoutInfo = sidecarWindowLayoutInfo;
+    }
+
+    @Nullable
+    @Override
+    public List<TestDisplayFeature> getDisplayFeatures() {
+        List<SidecarDisplayFeature> displayFeatures = mSidecarWindowLayoutInfo.displayFeatures;
+        return displayFeatures == null
+                ? null
+                : displayFeatures
+                        .stream()
+                        .map(TestSidecarDisplayFeature::create)
+                        .collect(Collectors.toList());
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return mSidecarWindowLayoutInfo.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof TestSidecarWindowLayoutInfo)) {
+            return false;
+        }
+        final TestSidecarWindowLayoutInfo other = (TestSidecarWindowLayoutInfo) obj;
+        return mSidecarWindowLayoutInfo.equals(other.mSidecarWindowLayoutInfo);
+    }
+
+    @Override
+    public int hashCode() {
+        return mSidecarWindowLayoutInfo.hashCode();
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/window-sidecar-release.aar b/tests/framework/base/windowmanager/jetpack/window-sidecar-release.aar
new file mode 100644
index 0000000..50f101d
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/window-sidecar-release.aar
Binary files differ
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
index f219994..8a5d21c 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
@@ -115,6 +115,7 @@
 
         mDm = mContext.getSystemService(DisplayManager.class);
         cleanupState();
+        mUseTaskOrganizer = false;
     }
 
     @After
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowContextTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowContextTests.java
index 9b113d5..05f1b09 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowContextTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowContextTests.java
@@ -27,8 +27,6 @@
 import android.view.View;
 import android.view.WindowManager;
 
-import androidx.test.filters.FlakyTest;
-
 import org.junit.Test;
 
 /**
@@ -40,7 +38,6 @@
 @Presubmit
 public class WindowContextTests extends WindowContextTestBase {
     @Test
-    @FlakyTest(bugId = 150251036)
     @AppModeFull
     public void testWindowContextConfigChanges() {
         final WindowManagerState.DisplayContent display =  createManagedVirtualDisplaySession()
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/TestTaskOrganizer.java b/tests/framework/base/windowmanager/util/src/android/server/wm/TestTaskOrganizer.java
index 5dec9e9..ca3f727 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/TestTaskOrganizer.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/TestTaskOrganizer.java
@@ -23,6 +23,7 @@
 
 import android.app.ActivityManager;
 import android.view.Display;
+import android.view.SurfaceControl;
 import android.window.TaskOrganizer;
 import android.window.WindowContainerTransaction;
 
@@ -135,7 +136,8 @@
     }
 
     @Override
-    public void onTaskAppeared(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
+    public void onTaskAppeared(@NonNull ActivityManager.RunningTaskInfo taskInfo,
+            SurfaceControl leash) {
         addTask(taskInfo);
     }
 
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
index c1863f9..917f7b3 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
@@ -50,6 +50,8 @@
     private static final String HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED =
             "HardKeyboardConfigurationBehaviorAllowed";
     private static final String INLINE_SUGGESTIONS_ENABLED = "InlineSuggestionsEnabled";
+    private static final String INLINE_SUGGESTION_VIEW_CONTENT_DESC =
+            "InlineSuggestionViewContentDesc";
 
     @NonNull
     private final PersistableBundle mBundle;
@@ -120,6 +122,11 @@
         return mBundle.getBoolean(INLINE_SUGGESTIONS_ENABLED);
     }
 
+    @Nullable
+    public String getInlineSuggestionViewContentDesc(@Nullable String defaultValue) {
+        return mBundle.getString(INLINE_SUGGESTION_VIEW_CONTENT_DESC, defaultValue);
+    }
+
     static Bundle serializeToBundle(@NonNull String eventCallbackActionName,
             @Nullable Builder builder) {
         final Bundle result = new Bundle();
@@ -261,5 +268,17 @@
             mBundle.putBoolean(INLINE_SUGGESTIONS_ENABLED, enabled);
             return this;
         }
+
+        /**
+         * Controls whether inline suggestions are enabled for {@link MockIme}. If enabled, a
+         * suggestion strip will be rendered at the top of the keyboard.
+         *
+         * @param contentDesc content description to be set to the inline suggestion View.
+         */
+        public Builder setInlineSuggestionViewContentDesc(@NonNull String contentDesc) {
+            mBundle.putString(INLINE_SUGGESTION_VIEW_CONTENT_DESC, contentDesc);
+            return this;
+        }
+
     }
 }
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index 279206e..951d1a7 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -28,7 +28,6 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.inputmethodservice.InputMethodService;
-import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -74,6 +73,8 @@
 import androidx.annotation.WorkerThread;
 
 import java.util.ArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
@@ -421,6 +422,10 @@
         private final View.OnLayoutChangeListener mLayoutListener;
 
         private final LinearLayout mLayout;
+
+        @Nullable
+        private final LinearLayout mSuggestionView;
+
         private boolean mDrawsBehindNavBar = false;
 
         KeyboardLayoutView(MockIme mockIme, @NonNull ImeSettings imeSettings,
@@ -444,14 +449,19 @@
                 final LayoutParams scrollViewParams = new LayoutParams(MATCH_PARENT, 100);
                 scrollView.setLayoutParams(scrollViewParams);
 
-                sSuggestionView = new LinearLayout(getContext());
-                sSuggestionView.setBackgroundColor(0xFFEEEEEE);
-                //TODO: Change magic id
-                sSuggestionView.setId(0x0102000b);
-                scrollView.addView(sSuggestionView,
-                        new LayoutParams(MATCH_PARENT, MATCH_PARENT));
+                final LinearLayout suggestionView = new LinearLayout(getContext());
+                suggestionView.setBackgroundColor(0xFFEEEEEE);
+                final String suggestionViewContentDesc =
+                        mSettings.getInlineSuggestionViewContentDesc(null /* default */);
+                if (suggestionViewContentDesc != null) {
+                    suggestionView.setContentDescription(suggestionViewContentDesc);
+                }
+                scrollView.addView(suggestionView, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
+                mSuggestionView = suggestionView;
 
                 mLayout.addView(scrollView);
+            } else {
+                mSuggestionView = null;
             }
 
             {
@@ -558,6 +568,24 @@
             super.onDetachedFromWindow();
             removeOnLayoutChangeListener(mLayoutListener);
         }
+
+        @MainThread
+        private void updateInlineSuggestions(
+                @NonNull PendingInlineSuggestions pendingInlineSuggestions) {
+            Log.d(TAG, "updateInlineSuggestions() called: " + pendingInlineSuggestions.mTotalCount);
+            if (mSuggestionView == null || !pendingInlineSuggestions.mValid.get()) {
+                return;
+            }
+            mSuggestionView.removeAllViews();
+            for (int i = 0; i < pendingInlineSuggestions.mTotalCount; i++) {
+                View view = pendingInlineSuggestions.mViews[i];
+                Size size = pendingInlineSuggestions.mViewSizes[i];
+                if (view == null || size == null) {
+                    continue;
+                }
+                mSuggestionView.addView(view, size.getWidth(), size.getHeight());
+            }
+        }
     }
 
     KeyboardLayoutView mView;
@@ -677,7 +705,6 @@
         return new ImeState(hasInputBinding, hasDummyInputConnectionConnection);
     }
 
-    private static LinearLayout sSuggestionView;
     private PendingInlineSuggestions mPendingInlineSuggestions;
 
     private static final class PendingInlineSuggestions {
@@ -700,77 +727,62 @@
     @MainThread
     @Override
     public InlineSuggestionsRequest onCreateInlineSuggestionsRequest(Bundle uiExtras) {
-        Log.d(TAG, "onCreateInlineSuggestionsRequest() called");
-        final ArrayList<InlinePresentationSpec> presentationSpecs = new ArrayList<>();
-        presentationSpecs.add(new InlinePresentationSpec.Builder(new Size(100, 100),
-                new Size(400, 100)).build());
-        presentationSpecs.add(new InlinePresentationSpec.Builder(new Size(100, 100),
-                new Size(400, 100)).build());
+        return getTracer().onCreateInlineSuggestionsRequest(() -> {
+            final ArrayList<InlinePresentationSpec> presentationSpecs = new ArrayList<>();
+            presentationSpecs.add(new InlinePresentationSpec.Builder(new Size(100, 100),
+                    new Size(400, 100)).build());
+            presentationSpecs.add(new InlinePresentationSpec.Builder(new Size(100, 100),
+                    new Size(400, 100)).build());
 
-        return new InlineSuggestionsRequest.Builder(presentationSpecs)
-                .setMaxSuggestionCount(6)
-                .build();
+            return new InlineSuggestionsRequest.Builder(presentationSpecs)
+                    .setMaxSuggestionCount(6)
+                    .build();
+        });
     }
 
 
     @MainThread
     @Override
-    public boolean onInlineSuggestionsResponse(InlineSuggestionsResponse response) {
-        Log.d(TAG,
-                "onInlineSuggestionsResponse() called: " + response.getInlineSuggestions().size());
-        final PendingInlineSuggestions pendingInlineSuggestions =
-                new PendingInlineSuggestions(response);
-        if (mPendingInlineSuggestions != null) {
-            mPendingInlineSuggestions.mValid.set(false);
-        }
-        mPendingInlineSuggestions = pendingInlineSuggestions;
-        if (pendingInlineSuggestions.mTotalCount == 0) {
-            updateInlineSuggestions(pendingInlineSuggestions);
-            return true;
-        }
-
-        for (int i = 0; i < pendingInlineSuggestions.mTotalCount; i++) {
-            final int index = i;
-            InlineSuggestion inlineSuggestion =
-                    pendingInlineSuggestions.mResponse.getInlineSuggestions().get(index);
-            Size size = inlineSuggestion.getInfo().getInlinePresentationSpec().getMaxSize();
-            inlineSuggestion.inflate(
-                    this,
-                    size,
-                    AsyncTask.THREAD_POOL_EXECUTOR,
-                    suggestionView -> {
-                        Log.d(TAG, "new inline suggestion view ready");
-                        if (suggestionView != null) {
-                            pendingInlineSuggestions.mViews[index] = suggestionView;
-                            pendingInlineSuggestions.mViewSizes[index] = size;
-                        }
-                        if (pendingInlineSuggestions.mInflatedViewCount.incrementAndGet()
-                                == pendingInlineSuggestions.mTotalCount
-                                && pendingInlineSuggestions.mValid.get()) {
-                            Log.d(TAG, "ready to display all suggestions");
-                            getMainExecutor().execute(
-                                    () -> updateInlineSuggestions(pendingInlineSuggestions));
-                        }
-                    });
-        }
-        return true;
-    }
-
-    @MainThread
-    private void updateInlineSuggestions(PendingInlineSuggestions pendingInlineSuggestions) {
-        Log.d(TAG, "updateInlineSuggestions() called: " + pendingInlineSuggestions.mTotalCount);
-        if (sSuggestionView == null || !pendingInlineSuggestions.mValid.get()) {
-            return;
-        }
-        sSuggestionView.removeAllViews();
-        for (int i = 0; i < pendingInlineSuggestions.mTotalCount; i++) {
-            View view = pendingInlineSuggestions.mViews[i];
-            Size size = pendingInlineSuggestions.mViewSizes[i];
-            if (view == null || size == null) {
-                continue;
+    public boolean onInlineSuggestionsResponse(@NonNull InlineSuggestionsResponse response) {
+        return getTracer().onInlineSuggestionsResponse(response, () -> {
+            final PendingInlineSuggestions pendingInlineSuggestions =
+                    new PendingInlineSuggestions(response);
+            if (mPendingInlineSuggestions != null) {
+                mPendingInlineSuggestions.mValid.set(false);
             }
-            sSuggestionView.addView(view, size.getWidth(), size.getHeight());
-        }
+            mPendingInlineSuggestions = pendingInlineSuggestions;
+            if (pendingInlineSuggestions.mTotalCount == 0) {
+                mView.updateInlineSuggestions(pendingInlineSuggestions);
+                return true;
+            }
+
+            final ExecutorService executorService = Executors.newCachedThreadPool();
+            for (int i = 0; i < pendingInlineSuggestions.mTotalCount; i++) {
+                final int index = i;
+                InlineSuggestion inlineSuggestion =
+                        pendingInlineSuggestions.mResponse.getInlineSuggestions().get(index);
+                Size size = inlineSuggestion.getInfo().getInlinePresentationSpec().getMaxSize();
+                inlineSuggestion.inflate(
+                        this,
+                        size,
+                        executorService,
+                        suggestionView -> {
+                            Log.d(TAG, "new inline suggestion view ready");
+                            if (suggestionView != null) {
+                                pendingInlineSuggestions.mViews[index] = suggestionView;
+                                pendingInlineSuggestions.mViewSizes[index] = size;
+                            }
+                            if (pendingInlineSuggestions.mInflatedViewCount.incrementAndGet()
+                                    == pendingInlineSuggestions.mTotalCount
+                                    && pendingInlineSuggestions.mValid.get()) {
+                                Log.d(TAG, "ready to display all suggestions");
+                                mMainHandler.post(() ->
+                                        mView.updateInlineSuggestions(pendingInlineSuggestions));
+                            }
+                        });
+            }
+            return true;
+        });
     }
 
     /**
@@ -864,45 +876,44 @@
             return result;
         }
 
-        public void onCreate(@NonNull Runnable runnable) {
+        void onCreate(@NonNull Runnable runnable) {
             recordEventInternal("onCreate", runnable);
         }
 
-        public void onConfigureWindow(Window win, boolean isFullscreen,
-                boolean isCandidatesOnly, @NonNull Runnable runnable) {
+        void onConfigureWindow(Window win, boolean isFullscreen, boolean isCandidatesOnly,
+                @NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             arguments.putBoolean("isFullscreen", isFullscreen);
             arguments.putBoolean("isCandidatesOnly", isCandidatesOnly);
             recordEventInternal("onConfigureWindow", runnable, arguments);
         }
 
-        public boolean onEvaluateFullscreenMode(@NonNull BooleanSupplier supplier) {
+        boolean onEvaluateFullscreenMode(@NonNull BooleanSupplier supplier) {
             return recordEventInternal("onEvaluateFullscreenMode", supplier::getAsBoolean);
         }
 
-        public boolean onEvaluateInputViewShown(@NonNull BooleanSupplier supplier) {
+        boolean onEvaluateInputViewShown(@NonNull BooleanSupplier supplier) {
             return recordEventInternal("onEvaluateInputViewShown", supplier::getAsBoolean);
         }
 
-        public View onCreateInputView(@NonNull Supplier<View> supplier) {
+        View onCreateInputView(@NonNull Supplier<View> supplier) {
             return recordEventInternal("onCreateInputView", supplier);
         }
 
-        public void onStartInput(EditorInfo editorInfo, boolean restarting,
-                @NonNull Runnable runnable) {
+        void onStartInput(EditorInfo editorInfo, boolean restarting, @NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             arguments.putParcelable("editorInfo", editorInfo);
             arguments.putBoolean("restarting", restarting);
             recordEventInternal("onStartInput", runnable, arguments);
         }
 
-        public void onWindowVisibilityChanged(@NonNull Runnable runnable, int visibility) {
+        void onWindowVisibilityChanged(@NonNull Runnable runnable, int visibility) {
             final Bundle arguments = new Bundle();
             arguments.putInt("visible", visibility);
             recordEventInternal("onWindowVisibilityChanged", runnable, arguments);
         }
 
-        public void onStartInputView(EditorInfo editorInfo, boolean restarting,
+        void onStartInputView(EditorInfo editorInfo, boolean restarting,
                 @NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             arguments.putParcelable("editorInfo", editorInfo);
@@ -910,31 +921,31 @@
             recordEventInternal("onStartInputView", runnable, arguments);
         }
 
-        public void onFinishInputView(boolean finishingInput, @NonNull Runnable runnable) {
+        void onFinishInputView(boolean finishingInput, @NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             arguments.putBoolean("finishingInput", finishingInput);
             recordEventInternal("onFinishInputView", runnable, arguments);
         }
 
-        public void onFinishInput(@NonNull Runnable runnable) {
+        void onFinishInput(@NonNull Runnable runnable) {
             recordEventInternal("onFinishInput", runnable);
         }
 
-        public boolean onKeyDown(int keyCode, KeyEvent event, @NonNull BooleanSupplier supplier) {
+        boolean onKeyDown(int keyCode, KeyEvent event, @NonNull BooleanSupplier supplier) {
             final Bundle arguments = new Bundle();
             arguments.putInt("keyCode", keyCode);
             arguments.putParcelable("event", event);
             return recordEventInternal("onKeyDown", supplier::getAsBoolean, arguments);
         }
 
-        public void onUpdateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo,
+        void onUpdateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo,
                 @NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             arguments.putParcelable("cursorAnchorInfo", cursorAnchorInfo);
             recordEventInternal("onUpdateCursorAnchorInfo", runnable, arguments);
         }
 
-        public boolean onShowInputRequested(int flags, boolean configChange,
+        boolean onShowInputRequested(int flags, boolean configChange,
                 @NonNull BooleanSupplier supplier) {
             final Bundle arguments = new Bundle();
             arguments.putInt("flags", flags);
@@ -942,66 +953,76 @@
             return recordEventInternal("onShowInputRequested", supplier::getAsBoolean, arguments);
         }
 
-        public void onDestroy(@NonNull Runnable runnable) {
+        void onDestroy(@NonNull Runnable runnable) {
             recordEventInternal("onDestroy", runnable);
         }
 
-        public void attachToken(IBinder token, @NonNull Runnable runnable) {
+        void attachToken(IBinder token, @NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             arguments.putBinder("token", token);
             recordEventInternal("attachToken", runnable, arguments);
         }
 
-        public void bindInput(InputBinding binding, @NonNull Runnable runnable) {
+        void bindInput(InputBinding binding, @NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             arguments.putParcelable("binding", binding);
             recordEventInternal("bindInput", runnable, arguments);
         }
 
-        public void unbindInput(@NonNull Runnable runnable) {
+        void unbindInput(@NonNull Runnable runnable) {
             recordEventInternal("unbindInput", runnable);
         }
 
-        public void showSoftInput(int flags, ResultReceiver resultReceiver,
-                @NonNull Runnable runnable) {
+        void showSoftInput(int flags, ResultReceiver resultReceiver, @NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             arguments.putInt("flags", flags);
             arguments.putParcelable("resultReceiver", resultReceiver);
             recordEventInternal("showSoftInput", runnable, arguments);
         }
 
-        public void hideSoftInput(int flags, ResultReceiver resultReceiver,
-                @NonNull Runnable runnable) {
+        void hideSoftInput(int flags, ResultReceiver resultReceiver, @NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             arguments.putInt("flags", flags);
             arguments.putParcelable("resultReceiver", resultReceiver);
             recordEventInternal("hideSoftInput", runnable, arguments);
         }
 
-        public AbstractInputMethodImpl onCreateInputMethodInterface(
+        AbstractInputMethodImpl onCreateInputMethodInterface(
                 @NonNull Supplier<AbstractInputMethodImpl> supplier) {
             return recordEventInternal("onCreateInputMethodInterface", supplier);
         }
 
-        public void onReceiveCommand(
-                @NonNull ImeCommand command, @NonNull Runnable runnable) {
+        void onReceiveCommand(@NonNull ImeCommand command, @NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             arguments.putBundle("command", command.toBundle());
             recordEventInternal("onReceiveCommand", runnable, arguments);
         }
 
-        public void onHandleCommand(
+        void onHandleCommand(
                 @NonNull ImeCommand command, @NonNull Supplier<Object> resultSupplier) {
             final Bundle arguments = new Bundle();
             arguments.putBundle("command", command.toBundle());
             recordEventInternal("onHandleCommand", resultSupplier, arguments);
         }
 
-        public void onInputViewLayoutChanged(@NonNull ImeLayoutInfo imeLayoutInfo,
+        void onInputViewLayoutChanged(@NonNull ImeLayoutInfo imeLayoutInfo,
                 @NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             imeLayoutInfo.writeToBundle(arguments);
             recordEventInternal("onInputViewLayoutChanged", runnable, arguments);
         }
+
+        InlineSuggestionsRequest onCreateInlineSuggestionsRequest(
+                @NonNull Supplier<InlineSuggestionsRequest> supplier) {
+            return recordEventInternal("onCreateInlineSuggestionsRequest", supplier);
+        }
+
+        boolean onInlineSuggestionsResponse(@NonNull InlineSuggestionsResponse response,
+                @NonNull BooleanSupplier supplier) {
+            final Bundle arguments = new Bundle();
+            arguments.putParcelable("response", response);
+            return recordEventInternal("onInlineSuggestionsResponse", supplier::getAsBoolean,
+                    arguments);
+        }
     }
 }
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
index e4d6319..e7abf6c 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
@@ -26,9 +26,11 @@
 import static com.android.cts.mockime.ImeEventStreamTestUtils.notExpectEvent;
 
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import android.os.SystemClock;
+import android.support.test.uiautomator.UiObject2;
 import android.text.TextUtils;
 import android.util.Pair;
 import android.view.View;
@@ -37,6 +39,7 @@
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.cts.util.EndToEndImeTestBase;
 import android.view.inputmethod.cts.util.TestActivity;
+import android.view.inputmethod.cts.util.TestWebView;
 import android.view.inputmethod.cts.util.UnlockScreenRule;
 import android.widget.EditText;
 import android.widget.LinearLayout;
@@ -248,4 +251,29 @@
             expectImeInvisible(TIMEOUT);
         }
     }
+
+    @Test
+    public void testShowHideKeyboardOnWebView() throws Exception {
+        try (MockImeSession imeSession = MockImeSession.create(
+                InstrumentationRegistry.getContext(),
+                InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+                new ImeSettings.Builder())) {
+            final ImeEventStream stream = imeSession.openEventStream();
+
+            final UiObject2 inputTextField = TestWebView.launchTestWebViewActivity(
+                    TimeUnit.SECONDS.toMillis(5));
+            assertNotNull("Editor must exists on WebView", inputTextField);
+
+            expectEvent(stream, event -> "onStartInput".equals(event.getEventName()), TIMEOUT);
+            notExpectEvent(stream, event -> "onStartInputView".equals(event.getEventName()),
+                    TIMEOUT);
+            expectImeInvisible(TIMEOUT);
+
+            inputTextField.click();
+            expectEvent(stream.copy(), showSoftInputMatcher(InputMethod.SHOW_EXPLICIT), TIMEOUT);
+            expectEvent(stream.copy(), event -> "onStartInputView".equals(event.getEventName()),
+                    TIMEOUT);
+            expectImeVisible(TIMEOUT);
+        }
+    }
 }
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestWebView.java b/tests/inputmethod/src/android/view/inputmethod/cts/util/TestWebView.java
new file mode 100644
index 0000000..5090d70
--- /dev/null
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/util/TestWebView.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod.cts.util;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+import com.android.compatibility.common.util.Timeout;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+/**
+ * A custom {@link WebView} class which provides a simple web page for verifying IME behavior.
+ */
+public class TestWebView {
+
+    private static final class Impl extends WebView {
+        private final static String MY_HTML =
+                "<html><body>Editor: <input type='text' name='testInput'></body></html>";
+        private UiDevice mUiDevice;
+
+        public Impl(Context context, UiDevice uiDevice) {
+            super(context);
+            mUiDevice = uiDevice;
+        }
+
+        private void loadEditorPage() {
+            super.loadData(MY_HTML, "text/html", "UTF-8");
+        }
+
+        private UiObject2 getInput(Timeout timeout) {
+            final BySelector selector = By.text("Editor: ");
+            UiObject2 label = null;
+            try {
+                label = timeout.run("waitForObject(" + selector + ")",
+                        () -> mUiDevice.findObject(selector));
+            } catch (Exception e) {
+            }
+            assertNotNull("Editor label must exists on WebView", label);
+
+            // Then the input is next.
+            final UiObject2 parent = label.getParent();
+            UiObject2 previous = null;
+            for (UiObject2 child : parent.getChildren()) {
+                if (label.equals(previous)) {
+                    if (child.getClassName().equals(EditText.class.getName())) {
+                        return child;
+                    }
+                }
+                previous = child;
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Not intended to be instantiated.
+     */
+    private TestWebView() {
+    }
+
+    public static UiObject2 launchTestWebViewActivity(long timeoutMs)
+            throws Exception {
+        final AtomicReference<UiObject2> inputTextFieldRef = new AtomicReference<>();
+        final AtomicReference<TestWebView.Impl> webViewRef = new AtomicReference<>();
+        final CountDownLatch latch = new CountDownLatch(1);
+        final Timeout timeoutForFindObj = new Timeout("UIOBJECT_FIND_TIMEOUT",
+                timeoutMs, 2F, timeoutMs);
+
+        TestActivity.startSync(activity -> {
+            final LinearLayout layout = new LinearLayout(activity);
+            final TestWebView.Impl webView = new Impl(activity, UiDevice.getInstance(
+                    InstrumentationRegistry.getInstrumentation()));
+            webView.setWebViewClient(new WebViewClient() {
+                @Override
+                public void onPageFinished(WebView view, String url) {
+                    latch.countDown();
+                }
+            });
+            webViewRef.set(webView);
+            layout.setOrientation(LinearLayout.VERTICAL);
+            layout.addView(webView);
+            webView.loadEditorPage();
+            return layout;
+        });
+
+        latch.await(timeoutMs, TimeUnit.MILLISECONDS);
+        inputTextFieldRef.set(webViewRef.get().getInput(timeoutForFindObj));
+        return inputTextFieldRef.get();
+    }
+}
diff --git a/tests/quickaccesswallet/AndroidManifest.xml b/tests/quickaccesswallet/AndroidManifest.xml
index 4ad90ab..4b6a994 100755
--- a/tests/quickaccesswallet/AndroidManifest.xml
+++ b/tests/quickaccesswallet/AndroidManifest.xml
@@ -34,6 +34,13 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.quickaccesswallet.QuickAccessWalletSettingsActivity">
+            <intent-filter>
+                <action android:name="android.service.quickaccesswallet.action.VIEW_WALLET_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
         <service
             android:name="android.quickaccesswallet.TestHostApduService"
             android:exported="true"
diff --git a/tests/quickaccesswallet/res/xml/quickaccesswallet_configuration.xml b/tests/quickaccesswallet/res/xml/quickaccesswallet_configuration.xml
index 1e14677..6563a11 100644
--- a/tests/quickaccesswallet/res/xml/quickaccesswallet_configuration.xml
+++ b/tests/quickaccesswallet/res/xml/quickaccesswallet_configuration.xml
@@ -16,5 +16,4 @@
 
 <quickaccesswallet-service
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:settingsActivity="android.quickaccesswallet.QuickAccessWalletSettingsActivity"
     android:targetActivity="android.quickaccesswallet.QuickAccessWalletActivity"/>
\ No newline at end of file
diff --git a/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java b/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java
index e7bf721..c523e1f 100755
--- a/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java
+++ b/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java
@@ -112,43 +112,21 @@
     @Test
     public void testIsWalletFeatureAvailableWhenDeviceLocked_checksSecureSettings() {
         QuickAccessWalletClient client = QuickAccessWalletClient.create(mContext);
-
-
-        String showNotificationsSetting = SettingsUtils.getSecureSetting(
-                Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
-        String allowPrivateNotificationsSetting = SettingsUtils.get(
-                Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+        String showCardsAndPasses = SettingsUtils.getSecureSetting(
+                Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT);
 
         try {
-            SettingsUtils.syncSet(mContext, Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
-                    SETTING_ENABLED);
-            SettingsUtils.syncSet(mContext, Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
+            SettingsUtils.syncSet(mContext, Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT,
                     SETTING_ENABLED);
             assertThat(client.isWalletFeatureAvailableWhenDeviceLocked()).isTrue();
 
-            SettingsUtils.syncSet(mContext, Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
-                    SETTING_ENABLED);
-            SettingsUtils.syncSet(mContext, Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
-                    SETTING_DISABLED);
-            assertThat(client.isWalletFeatureAvailableWhenDeviceLocked()).isFalse();
-
-            SettingsUtils.syncSet(mContext, Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
-                    SETTING_DISABLED);
-            SettingsUtils.syncSet(mContext, Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
-                    SETTING_ENABLED);
-            assertThat(client.isWalletFeatureAvailableWhenDeviceLocked()).isFalse();
-
-            SettingsUtils.syncSet(mContext, Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
-                    SETTING_DISABLED);
-            SettingsUtils.syncSet(mContext, Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
+            SettingsUtils.syncSet(mContext, Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT,
                     SETTING_DISABLED);
             assertThat(client.isWalletFeatureAvailableWhenDeviceLocked()).isFalse();
         } finally {
-            // return settings to original values
-            SettingsUtils.syncSet(mContext, Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
-                    showNotificationsSetting);
-            SettingsUtils.syncSet(mContext, Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
-                    allowPrivateNotificationsSetting);
+            // return setting to original value
+            SettingsUtils.syncSet(mContext, Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT,
+                    showCardsAndPasses);
         }
     }
 
@@ -438,7 +416,7 @@
     }
 
     @Test
-    public void testCreateWalletSettingsIntent_parsesXmlAndUsesCorrectIntentAction() {
+    public void testCreateWalletSettingsIntent_usesSettingsActionToFindAppropriateActivity() {
         Intent settingsIntent =
                 QuickAccessWalletClient.create(mContext).createWalletSettingsIntent();
         assertThat(settingsIntent).isNotNull();
diff --git a/tests/sensor/src/android/hardware/cts/SensorTest.java b/tests/sensor/src/android/hardware/cts/SensorTest.java
index 49e3c27..bde6e0e 100644
--- a/tests/sensor/src/android/hardware/cts/SensorTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorTest.java
@@ -731,9 +731,11 @@
                 }
                 if (mFlushWhileIdle) {
                     SensorCtsHelper.makeMyPackageIdle();
+                    sensorManager.assertFlushFail();
+                } else {
+                    CountDownLatch flushLatch = sensorManager.requestFlush();
+                    listener.waitForFlushComplete(flushLatch, true);
                 }
-                CountDownLatch flushLatch = sensorManager.requestFlush();
-                listener.waitForFlushComplete(flushLatch, true);
             } finally {
                 sensorManager.unregisterListener();
                 if (mFlushWhileIdle) {
diff --git a/tests/sensor/src/android/hardware/cts/helpers/TestSensorManager.java b/tests/sensor/src/android/hardware/cts/helpers/TestSensorManager.java
index 7c69649..aba6d49 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/TestSensorManager.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/TestSensorManager.java
@@ -156,6 +156,20 @@
     }
 
     /**
+     * Call {@link SensorManager#flush(SensorEventListener)} and asserts that it fails.
+     */
+    public void assertFlushFail() {
+        if (mTestSensorEventListener == null) {
+            Log.w(LOG_TAG, "No listener registered, returning.");
+            return;
+        }
+        Assert.assertFalse(
+                SensorCtsHelper.formatAssertionMessage(
+                    "Flush succeeded unexpectedly", mEnvironment),
+                mSensorManager.flush(mTestSensorEventListener));
+    }
+
+    /**
      * Call {@link SensorManager#flush(SensorEventListener)}. This method will perform a no-op if
      * the sensor is not registered.
      *
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BasicAdapterTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BasicAdapterTest.java
index 8616a6d..ab60c67 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BasicAdapterTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BasicAdapterTest.java
@@ -19,30 +19,51 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothServerSocket;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 import java.io.IOException;
 import java.util.Set;
 import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * Very basic test, just of the static methods of {@link
  * BluetoothAdapter}.
  */
 public class BasicAdapterTest extends AndroidTestCase {
+    private static final String TAG = "BasicAdapterTest";
     private static final int DISABLE_TIMEOUT = 8000;  // ms timeout for BT disable
     private static final int ENABLE_TIMEOUT = 10000;  // ms timeout for BT enable
     private static final int POLL_TIME = 400;         // ms to poll BT state
     private static final int CHECK_WAIT_TIME = 1000;  // ms to wait before enable/disable
+    private static final int SET_NAME_TIMEOUT = 5000; // ms timeout for setting adapter name
 
     private boolean mHasBluetooth;
+    private ReentrantLock mAdapterNameChangedlock;
+    private Condition mConditionAdapterNameChanged;
+    private boolean mIsAdapterNameChanged;
 
     public void setUp() throws Exception {
         super.setUp();
 
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        mContext.registerReceiver(mAdapterNameChangeReceiver, filter);
+
         mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_BLUETOOTH);
+        mAdapterNameChangedlock = new ReentrantLock();
+        mConditionAdapterNameChanged = mAdapterNameChangedlock.newCondition();
+        mIsAdapterNameChanged = false;
     }
 
     public void test_getDefaultAdapter() {
@@ -140,7 +161,7 @@
         assertTrue(BluetoothAdapter.checkBluetoothAddress(adapter.getAddress()));
     }
 
-    public void test_getName() {
+    public void test_setName_getName() {
         if (!mHasBluetooth) {
             // Skip the test if bluetooth is not present.
             return;
@@ -150,6 +171,19 @@
 
         String name = adapter.getName();
         assertNotNull(name);
+
+        // Check renaming the adapter
+        String genericName = "Generic Device 1";
+        assertTrue(adapter.setName(genericName));
+        assertTrue(waitForAdapterNameChange());
+        mIsAdapterNameChanged = false;
+        assertEquals(genericName, adapter.getName());
+
+        // Check setting adapter back to original name
+        assertTrue(adapter.setName(name));
+        assertTrue(waitForAdapterNameChange());
+        mIsAdapterNameChanged = false;
+        assertEquals(name, adapter.getName());
     }
 
     public void test_getBondedDevices() {
@@ -289,4 +323,40 @@
             Thread.sleep(t);
         } catch (InterruptedException e) {}
     }
+
+    private boolean waitForAdapterNameChange() {
+        mAdapterNameChangedlock.lock();
+        try {
+            // Wait for the Adapter name to be changed
+            while (!mIsAdapterNameChanged) {
+                if (!mConditionAdapterNameChanged.await(
+                        SET_NAME_TIMEOUT, TimeUnit.MILLISECONDS)) {
+                    Log.e(TAG, "Timeout while waiting for adapter name change");
+                    break;
+                }
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForAdapterNameChange: interrrupted");
+        } finally {
+            mAdapterNameChangedlock.unlock();
+        }
+        return mIsAdapterNameChanged;
+    }
+
+    private final BroadcastReceiver mAdapterNameChangeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) {
+                mAdapterNameChangedlock.lock();
+                mIsAdapterNameChanged = true;
+                try {
+                    mConditionAdapterNameChanged.signal();
+                } catch (IllegalMonitorStateException ex) {
+                } finally {
+                    mAdapterNameChangedlock.unlock();
+                }
+            }
+        }
+    };
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
index 687e316..867f8a3 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
@@ -2598,6 +2598,17 @@
     }
 
     @Test(expected = FileNotFoundException.class)
+    public void testUriWithoutScheme() throws IOException {
+        Uri uri = new Uri.Builder()
+                .authority("authority")
+                .appendPath("missing")
+                .appendPath("scheme")
+                .build();
+        ImageDecoder.Source src = ImageDecoder.createSource(getContentResolver(), uri);
+        ImageDecoder.decodeDrawable(src);
+    }
+
+    @Test(expected = FileNotFoundException.class)
     public void testBadCallable() throws IOException {
         ImageDecoder.Source src = ImageDecoder.createSource(() -> null);
         ImageDecoder.decodeDrawable(src);
diff --git a/tests/tests/media/src/android/media/cts/AudioHelper.java b/tests/tests/media/src/android/media/cts/AudioHelper.java
index 7208e51..a0f8e47 100644
--- a/tests/tests/media/src/android/media/cts/AudioHelper.java
+++ b/tests/tests/media/src/android/media/cts/AudioHelper.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.DeviceReportLog;
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
@@ -251,6 +252,7 @@
         }
     }
 
+    @CddTest(requirement="5.10/C-1-6,C-1-7")
     public static class TimestampVerifier {
 
         // CDD 5.6 1ms timestamp accuracy
@@ -259,7 +261,7 @@
         private static final double TEST_STD_JITTER_MS_WARN = 1.;    // CDD requirement warning
 
         // CDD 5.6 100ms track startup latency
-        private static final double TEST_STARTUP_TIME_MS_ALLOWED = 500.; // flaky tolerance 5x
+        private final double TEST_STARTUP_TIME_MS_ALLOWED; // CDD requirement error
         private static final double TEST_STARTUP_TIME_MS_WARN = 100.;    // CDD requirement warning
 
         private static final int MILLIS_PER_SECOND = 1000;
@@ -280,9 +282,12 @@
         private double mMaxAbsJitterMs = 0.;
         private int mWarmupCount = 0;
 
-        public TimestampVerifier(@Nullable String tag, @IntRange(from=4000) int sampleRate) {
+        public TimestampVerifier(@Nullable String tag, @IntRange(from=4000) int sampleRate,
+                boolean isProAudioDevice) {
             mTag = tag;  // Log accepts null
             mSampleRate = sampleRate;
+            // For pro audio, allow slightly higher than MUST value to account for variability.
+            TEST_STARTUP_TIME_MS_ALLOWED = isProAudioDevice ? 300. /* MUST is 200. */ : 500.;
         }
 
         public int getJitterCount() { return mJitterCount; }
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index 6268466..e4d4f62 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -1538,7 +1538,7 @@
         mAudioManager.adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 66747, 0);
     }
 
-    @CddTest(requirement="5.4.4/C-4-1")
+    @CddTest(requirement="5.4.1/C-1-4")
     public void testGetMicrophones() throws Exception {
         if (!mContext.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_MICROPHONE)) {
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordTest.java b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
index 5cc58ce..2b342c8 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
@@ -576,7 +576,8 @@
                 // For 16 bit data, use shorts
                 final short[] shortData = new short[BUFFER_SAMPLES];
                 final AudioHelper.TimestampVerifier tsVerifier =
-                        new AudioHelper.TimestampVerifier(TAG, RECORD_SAMPLE_RATE);
+                        new AudioHelper.TimestampVerifier(TAG, RECORD_SAMPLE_RATE,
+                                isProAudioDevice());
 
                 while (samplesRead < targetSamples) {
                     final int amount = samplesRead == 0 ? numChannels :
@@ -963,7 +964,7 @@
         Log.i(TAG, "******");
     }
 
-    @CddTest(requirement="5.4.4/C-4-1")
+    @CddTest(requirement="5.4.1/C-1-4")
     @Test
     public void testGetActiveMicrophones() throws Exception {
         if (!hasMicrophone()) {
@@ -1600,6 +1601,11 @@
                 PackageManager.FEATURE_AUDIO_LOW_LATENCY);
     }
 
+    private boolean isProAudioDevice() {
+        return getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_AUDIO_PRO);
+    }
+
     private void verifyContinuousTimestamps(
             AudioTimestamp startTs, AudioTimestamp stopTs, int sampleRate)
             throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/AudioRecord_BufferSizeTest.java b/tests/tests/media/src/android/media/cts/AudioRecord_BufferSizeTest.java
index 600bf8c..837a4a8 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecord_BufferSizeTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecord_BufferSizeTest.java
@@ -23,6 +23,7 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.PollingCheck;
 
 import java.util.ArrayList;
@@ -40,10 +41,12 @@
         11025,
         16000,
         44100,
+        48000,
     };
 
     private AudioRecord mAudioRecord;
 
+    @CddTest(requirement="5.4.1/C-1-1")
     public void testGetMinBufferSize() throws Exception {
         if (!hasMicrophone()) {
             return;
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackTest.java b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
index d9c2f50..f5f0420 100755
--- a/tests/tests/media/src/android/media/cts/AudioTrackTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
@@ -2099,6 +2099,11 @@
                 .isLowRamDevice();
     }
 
+    private boolean isProAudioDevice() {
+        return getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_AUDIO_PRO);
+    }
+
     @Test
     public void testGetTimestamp() throws Exception {
         if (!hasAudioOutput()) {
@@ -2185,7 +2190,7 @@
 
             long framesWritten = 0;
             final AudioHelper.TimestampVerifier tsVerifier =
-                    new AudioHelper.TimestampVerifier(TAG, sampleRate);
+                    new AudioHelper.TimestampVerifier(TAG, sampleRate, isProAudioDevice());
             for (int i = 0; i < TEST_LOOP_CNT; ++i) {
                 final long trackWriteTimeNs = System.nanoTime();
 
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index b059301..44e724f 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -629,7 +629,7 @@
         mMediaRecorder.setMaxFileSize(MAX_FILE_SIZE * 10);
     }
 
-    @CddTest(requirement="5.4.4/C-4-1")
+    @CddTest(requirement="5.4.1/C-1-4")
     public void testGetActiveMicrophones() throws Exception {
         if (!hasMicrophone() || !hasAac()) {
             MediaUtils.skipTest("no audio codecs or microphone");
diff --git a/tests/tests/notificationlegacy/notificationlegacy29/Android.bp b/tests/tests/notificationlegacy/notificationlegacy29/Android.bp
index 8260a66..aabff61 100644
--- a/tests/tests/notificationlegacy/notificationlegacy29/Android.bp
+++ b/tests/tests/notificationlegacy/notificationlegacy29/Android.bp
@@ -31,6 +31,7 @@
         "cts",
         "vts10",
         "general-tests",
+        "mts"
     ],
     sdk_version: "test_current",
     target_sdk_version: "29",
diff --git a/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationAssistantServiceTest.java b/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationAssistantServiceTest.java
index a69c595..19465b8 100644
--- a/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationAssistantServiceTest.java
+++ b/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationAssistantServiceTest.java
@@ -36,6 +36,7 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
 import android.provider.Telephony;
 import android.service.notification.Adjustment;
 import android.service.notification.NotificationAssistantService;
@@ -52,9 +53,13 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.BufferedReader;
 import java.io.FileInputStream;
+import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Reader;
+import java.nio.CharBuffer;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
@@ -191,7 +196,7 @@
     }
 
     @Test
-    public void testAdjustNotification_rankingScoreKey() throws Exception {
+    public void testAdjustNotifications_rankingScoreKey() throws Exception {
         setUpListeners();
 
         try {
@@ -225,12 +230,11 @@
             signals.putFloat(Adjustment.KEY_RANKING_SCORE, rankingScore1);
             Adjustment adjustment = new Adjustment(sbn1.getPackageName(), sbn1.getKey(), signals, "",
                     sbn1.getUser());
-            mNotificationAssistantService.adjustNotification(adjustment);
-            signals = new Bundle();
-            signals.putFloat(Adjustment.KEY_RANKING_SCORE, rankingScore2);
-            adjustment = new Adjustment(sbn2.getPackageName(), sbn2.getKey(), signals, "",
+            Bundle signals2 = new Bundle();
+            signals2.putFloat(Adjustment.KEY_RANKING_SCORE, rankingScore2);
+            Adjustment adjustment2 = new Adjustment(sbn2.getPackageName(), sbn2.getKey(), signals2, "",
                     sbn2.getUser());
-            mNotificationAssistantService.adjustNotification(adjustment);
+            mNotificationAssistantService.adjustNotifications(List.of(adjustment, adjustment2));
             Thread.sleep(SLEEP_TIME); // wait for adjustments to be processed
 
             mNotificationListenerService.mRankingMap.getRanking(sbn1.getKey(), out1);
@@ -454,6 +458,60 @@
     }
 
     @Test
+    public void testOnNotificationSnoozedUntilContext() throws Exception {
+        final String snoozeContext = "@SnoozeContext1@";
+
+        setUpListeners(); // also enables assistant
+
+        sendNotification(1001, ICON_ID);
+        StatusBarNotification sbn = getFirstNotificationFromPackage(TestNotificationListener.PKG);
+
+        // simulate the user snoozing the notification
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        runCommand(String.format("cmd notification snooze --condition %s %s", snoozeContext,
+                sbn.getKey()), instrumentation);
+
+        Thread.sleep(SLEEP_TIME);
+
+        assertTrue(String.format("snoozed notification <%s> was not removed", sbn.getKey()),
+                mNotificationListenerService.checkRemovedKey(sbn.getKey()));
+
+        assertEquals(String.format("snoozed notification <%s> was not observed by NAS", sbn.getKey()),
+                sbn.getKey(), mNotificationAssistantService.snoozedKey);
+        assertEquals(snoozeContext, mNotificationAssistantService.snoozedUntilContext);
+    }
+
+    @Test
+    public void testUnsnoozeFromNAS() throws Exception {
+        final String snoozeContext = "@SnoozeContext2@";
+
+        setUpListeners(); // also enables assistant
+
+        sendNotification(1002, ICON_ID);
+        StatusBarNotification sbn = getFirstNotificationFromPackage(TestNotificationListener.PKG);
+
+        // simulate the user snoozing the notification
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        runCommand(String.format("cmd notification snooze --context %s %s", snoozeContext,
+            sbn.getKey()), instrumentation);
+
+        Thread.sleep(SLEEP_TIME);
+
+        // unsnooze from listener
+        mNotificationAssistantService = TestNotificationAssistant.getInstance();
+        android.util.Log.v(TAG, "unsnoozing from listener: " + sbn.getKey());
+        mNotificationAssistantService.unsnoozeNotification(sbn.getKey());
+
+        Thread.sleep(SLEEP_TIME);
+
+        NotificationListenerService.Ranking out = new NotificationListenerService.Ranking();
+        boolean found = mNotificationListenerService.mRankingMap.getRanking(sbn.getKey(), out);
+        assertTrue("notification <" + sbn.getKey()
+                + "> was not restored when unsnoozed from listener",
+                found);
+    }
+
+    @Test
     public void testOnActionInvoked_methodExists() throws Exception {
         setUpListeners();
         final Intent intent = new Intent(Intent.ACTION_MAIN, Telephony.Threads.CONTENT_URI);
@@ -651,12 +709,14 @@
     private void runCommand(String command, Instrumentation instrumentation) throws IOException {
         UiAutomation uiAutomation = instrumentation.getUiAutomation();
         // Execute command
+        System.out.println("runCommand: <<<" + command + ">>>");
         try (ParcelFileDescriptor fd = uiAutomation.executeShellCommand(command)) {
             assertNotNull("Failed to execute shell command: " + command, fd);
             // Wait for the command to finish by reading until EOF
-            try (InputStream in = new FileInputStream(fd.getFileDescriptor())) {
-                byte[] buffer = new byte[4096];
-                while (in.read(buffer) > 0) {
+            try (BufferedReader in = new BufferedReader(new FileReader(fd.getFileDescriptor()))) {
+                String line;
+                while (null != (line = in.readLine())) {
+                    android.util.Log.v(TAG, "runCommand: output: " + line);
                 }
             } catch (IOException e) {
                 throw new IOException("Could not read stdout of command: " + command, e);
diff --git a/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/TestNotificationAssistant.java b/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/TestNotificationAssistant.java
index a70f6c6..3830458 100644
--- a/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/TestNotificationAssistant.java
+++ b/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/TestNotificationAssistant.java
@@ -36,6 +36,8 @@
     int notificationVisibleCount = 0;
     int notificationSeenCount = 0;
     int notificationHiddenCount = 0;
+    String snoozedKey;
+    String snoozedUntilContext;
     private NotificationManager mNotificationManager;
 
     public static String getId() {
@@ -73,6 +75,8 @@
     @Override
     public void onNotificationSnoozedUntilContext(StatusBarNotification statusBarNotification,
             String s) {
+        snoozedKey = statusBarNotification.getKey();
+        snoozedUntilContext = s;
     }
 
     @Override
diff --git a/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/TestNotificationListener.java b/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/TestNotificationListener.java
index aea3914..a7f068c 100644
--- a/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/TestNotificationListener.java
+++ b/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/TestNotificationListener.java
@@ -37,6 +37,13 @@
             sNotificationListenerInstance = null;
     boolean isConnected;
 
+    public boolean checkRemovedKey(String key) {
+        for (StatusBarNotification sbn : mRemoved) {
+            if (sbn.getKey().equals(key)) return true;
+        }
+        return false;
+    }
+
     public static String getId() {
         return String.format("%s/%s", TestNotificationListener.class.getPackage().getName(),
                 TestNotificationListener.class.getName());
@@ -76,6 +83,7 @@
 
     @Override
     public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+        android.util.Log.v(TAG, "notification posted: " + sbn);
         if (!PKG.equals(sbn.getPackageName())) {
             return;
         }
@@ -85,9 +93,11 @@
 
     @Override
     public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
+        android.util.Log.v(TAG, "notification removed: " + sbn);
         if (!mTestPackages.contains(sbn.getPackageName())) {
             return;
         }
+        android.util.Log.v(TAG, "adding to removed: " + sbn);
         mRankingMap = rankingMap;
         mRemoved.add(sbn);
     }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9536/Android.bp b/tests/tests/os/AutoRevokeWhitelistedDummyApp/Android.bp
similarity index 64%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2018-9536/Android.bp
copy to tests/tests/os/AutoRevokeWhitelistedDummyApp/Android.bp
index 16f9474..d957080 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9536/Android.bp
+++ b/tests/tests/os/AutoRevokeWhitelistedDummyApp/Android.bp
@@ -1,3 +1,4 @@
+//
 // Copyright (C) 2020 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,17 +12,19 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-cc_test {
-    name: "CVE-2018-9536",
-    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp"],
-    include_dirs: [
-        "external/aac/libFDK/include",
-        "external/aac/libSYS/include",
-        "cts/hostsidetests/securitybulletin/securityPatch/includes",
+android_test_helper_app {
+    name: "CtsAutoRevokeWhitelistedDummyApp",
+    defaults: ["cts_defaults"],
+    sdk_version: "test_current",
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts",
+        "vts10",
+        "mts",
+        "general-tests",
     ],
-    shared_libs: [
-        "libbluetooth"
-    ],
+    srcs: ["src/**/*.java", "src/**/*.kt"],
 }
diff --git a/tests/tests/os/AutoRevokeWhitelistedDummyApp/AndroidManifest.xml b/tests/tests/os/AutoRevokeWhitelistedDummyApp/AndroidManifest.xml
new file mode 100644
index 0000000..5c253ee
--- /dev/null
+++ b/tests/tests/os/AutoRevokeWhitelistedDummyApp/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--s
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.os.cts.autorevokewhitelisteddummyapp">
+
+    <uses-permission android:name="android.permission.READ_CALENDAR" />
+
+    <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="30" />
+
+    <application android:autoRevokePermissions="disallowed">
+        <activity android:name="android.os.cts.autorevokewhitelisteddummyapp.MainActivity"
+                  android:exported="true"
+                  android:visibleToInstantApps="true" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
+
diff --git a/tests/tests/os/AutoRevokeWhitelistedDummyApp/src/android/os/cts/autorevokewhitelisteddummyapp/MainActivity.kt b/tests/tests/os/AutoRevokeWhitelistedDummyApp/src/android/os/cts/autorevokewhitelisteddummyapp/MainActivity.kt
new file mode 100644
index 0000000..6e59224
--- /dev/null
+++ b/tests/tests/os/AutoRevokeWhitelistedDummyApp/src/android/os/cts/autorevokewhitelisteddummyapp/MainActivity.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.cts.autorevokewhitelisteddummyapp
+
+import android.app.Activity
+import android.os.Bundle
+import android.widget.LinearLayout
+import android.widget.LinearLayout.VERTICAL
+import android.widget.TextView
+
+class MainActivity : Activity() {
+
+    val whitelistStatus by lazy { TextView(this) }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        setContentView(LinearLayout(this).apply {
+            orientation = VERTICAL
+
+            addView(whitelistStatus)
+        })
+
+        requestPermissions(arrayOf("android.permission.READ_CALENDAR"), 0)
+    }
+
+    override fun onResume() {
+        super.onResume()
+
+        whitelistStatus.text = "Auto-revoke whitelisted: " + packageManager.isAutoRevokeWhitelisted
+    }
+}
diff --git a/tests/tests/os/CtsOsTestCases.xml b/tests/tests/os/CtsOsTestCases.xml
index 3718c59..d1ab773 100644
--- a/tests/tests/os/CtsOsTestCases.xml
+++ b/tests/tests/os/CtsOsTestCases.xml
@@ -36,5 +36,8 @@
     <!-- Load additional APKs onto device -->
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="push" value="CtsAutoRevokeDummyApp.apk->/data/local/tmp/cts/os/CtsAutoRevokeDummyApp.apk" />
+        <option
+            name="push"
+            value="CtsAutoRevokeWhitelistedDummyApp.apk->/data/local/tmp/cts/os/CtsAutoRevokeWhitelistedDummyApp.apk" />
     </target_preparer>
 </configuration>
diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
index 45ea4b8..ea58070 100644
--- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
+++ b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
@@ -26,7 +26,7 @@
 import android.net.Uri
 import android.platform.test.annotations.AppModeFull
 import android.provider.DeviceConfig
-import android.provider.Settings.*
+import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
 import android.support.test.uiautomator.By
 import android.support.test.uiautomator.BySelector
 import android.support.test.uiautomator.UiObject2
@@ -34,7 +34,8 @@
 import android.view.accessibility.AccessibilityNodeInfo
 import android.widget.Switch
 import com.android.compatibility.common.util.SystemUtil
-import com.android.compatibility.common.util.SystemUtil.*
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
 import com.android.compatibility.common.util.ThrowingSupplier
 import com.android.compatibility.common.util.UiAutomatorUtils
 import com.android.compatibility.common.util.UiDumpUtils
@@ -46,7 +47,10 @@
 import java.util.regex.Pattern
 
 private const val APK_PATH = "/data/local/tmp/cts/os/CtsAutoRevokeDummyApp.apk"
+private const val APK_WHITELISTED_PATH =
+        "/data/local/tmp/cts/os/CtsAutoRevokeWhitelistedDummyApp.apk"
 private const val APK_PACKAGE_NAME = "android.os.cts.autorevokedummyapp"
+private const val APK_WHITELISTED_PACKAGE_NAME = "android.os.cts.autorevokewhitelisteddummyapp"
 
 /**
  * Test for auto revoke
@@ -68,6 +72,7 @@
                 eventually {
                     assertPermission(PERMISSION_GRANTED)
                 }
+                goBack()
                 goHome()
                 Thread.sleep(5)
 
@@ -79,7 +84,7 @@
                     assertPermission(PERMISSION_DENIED)
                 }
                 runShellCommand("cmd statusbar expand-notifications")
-                waitFindObject(By.text("App permissions automatically removed"))
+                waitFindObject(By.textContains("unused app"))
                         .click()
                 waitFindObject(By.text(APK_PACKAGE_NAME))
                 waitFindObject(By.text("Calendar permission removed"))
@@ -114,7 +119,7 @@
     @AppModeFull(reason = "Uses separate apps for testing")
     fun testAutoRevoke_userWhitelisting() {
         wakeUpScreen()
-        withUnusedThresholdMs(TimeUnit.DAYS.toMillis(30)) {
+        withUnusedThresholdMs(4L) {
             withDummyApp {
                 // Setup
                 startApp()
@@ -133,12 +138,39 @@
                     assertFalse(getWhitelistToggle().isChecked)
                 }
 
+                // Run
+                goBack()
+                goBack()
+                goBack()
+                runAutoRevoke()
+                Thread.sleep(500L)
+
                 // Verify
-                goBack()
-                goBack()
-                goBack()
                 startApp()
                 assertWhitelistState(true)
+                assertPermission(PERMISSION_GRANTED)
+            }
+        }
+    }
+
+    @AppModeFull(reason = "Uses separate apps for testing")
+    fun testAutoRevoke_manifestWhitelisting() {
+        wakeUpScreen()
+        withUnusedThresholdMs(5L) {
+            withDummyApp(APK_WHITELISTED_PATH, APK_WHITELISTED_PACKAGE_NAME) {
+                // Setup
+                startApp(APK_WHITELISTED_PACKAGE_NAME)
+                clickPermissionAllow()
+                assertWhitelistState(true)
+
+                // Run
+                goHome()
+                Thread.sleep(20L)
+                runAutoRevoke()
+                Thread.sleep(500L)
+
+                // Verify
+                assertPermission(PERMISSION_GRANTED, APK_WHITELISTED_PACKAGE_NAME)
             }
         }
     }
@@ -201,19 +233,19 @@
 
     private inline fun <T> withUnusedThresholdMs(threshold: Long, action: () -> T): T {
         return withDeviceConfig(
-                "permissions", "auto_revoke_unused_threshold_millis", threshold.toString(), action)
+                "permissions", "auto_revoke_unused_threshold_millis2", threshold.toString(), action)
     }
 
-    private fun installApp() {
-        assertThat(runShellCommand("pm install -r $APK_PATH"), containsString("Success"))
+    private fun installApp(apk: String = APK_PATH) {
+        assertThat(runShellCommand("pm install -r $apk"), containsString("Success"))
     }
 
-    private fun uninstallApp() {
-        assertThat(runShellCommand("pm uninstall $APK_PACKAGE_NAME"), containsString("Success"))
+    private fun uninstallApp(packageName: String = APK_PACKAGE_NAME) {
+        assertThat(runShellCommand("pm uninstall $packageName"), containsString("Success"))
     }
 
-    private fun startApp() {
-        runShellCommand("am start -n $APK_PACKAGE_NAME/$APK_PACKAGE_NAME.MainActivity")
+    private fun startApp(packageName: String = APK_PACKAGE_NAME) {
+        runShellCommand("am start -n $packageName/$packageName.MainActivity")
     }
 
     private fun goHome() {
@@ -229,16 +261,20 @@
                 .click()
     }
 
-    private inline fun withDummyApp(action: () -> Unit) {
-        installApp()
+    private inline fun withDummyApp(
+        apk: String = APK_PATH,
+        packageName: String = APK_PACKAGE_NAME,
+        action: () -> Unit
+    ) {
+        installApp(apk)
         try {
             action()
         } finally {
-            uninstallApp()
+            uninstallApp(packageName)
         }
     }
 
-    private fun assertPermission(state: Int) {
+    private fun assertPermission(state: Int, packageName: String = APK_PACKAGE_NAME) {
         // For some reason this incorrectly always returns PERMISSION_DENIED
 //        runWithShellPermissionIdentity {
 //            assertEquals(
@@ -248,7 +284,7 @@
 
         try {
             context.startActivity(Intent(ACTION_APPLICATION_DETAILS_SETTINGS)
-                    .setData(Uri.fromParts("package", APK_PACKAGE_NAME, null))
+                    .setData(Uri.fromParts("package", packageName, null))
                     .addFlags(FLAG_ACTIVITY_NEW_TASK))
 
             waitFindObject(byTextIgnoreCase("Permissions")).click()
diff --git a/tests/tests/os/src/android/os/cts/HidlMemoryTest.java b/tests/tests/os/src/android/os/cts/HidlMemoryTest.java
new file mode 100644
index 0000000..f83bcc3
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/HidlMemoryTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.HidlMemory;
+import android.os.NativeHandle;
+
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class HidlMemoryTest {
+    @Test
+    public void testAccessors() {
+        NativeHandle handle = new NativeHandle();
+        HidlMemory mem = new HidlMemory("some name", 123, handle);
+        assertEquals("some name", mem.getName());
+        assertEquals(123, mem.getSize());
+        assertTrue(handle == mem.getHandle());
+    }
+
+    @Test
+    public void testClose() throws IOException {
+        NativeHandle handle = new NativeHandle();
+        HidlMemory mem = new HidlMemory("some name", 123, handle);
+        assertFalse(isHandleClosed(handle));
+        mem.close();
+        assertTrue(isHandleClosed(handle));
+    }
+
+    @Test
+    public void testCloseNullHandle() throws IOException {
+        HidlMemory mem = new HidlMemory("some name", 123, null);
+        mem.close();
+    }
+
+    @Test
+    public void testRelease() throws IOException {
+        NativeHandle handle = new NativeHandle();
+        HidlMemory mem = new HidlMemory("some name", 123, handle);
+        assertTrue(mem.getHandle() == handle);
+        NativeHandle released = mem.releaseHandle();
+        assertTrue(mem.getHandle() == null);
+        assertTrue(released == handle);
+        assertFalse(isHandleClosed(handle));
+        handle.close();
+    }
+
+    @Test
+    public void testDup() throws IOException {
+        NativeHandle handle = new NativeHandle();
+        HidlMemory mem = new HidlMemory("some name", 123, handle);
+
+        HidlMemory dup = mem.dup();
+        assertEquals("some name", dup.getName());
+        assertEquals(123, dup.getSize());
+        assertFalse(dup.getHandle() == handle);
+
+        assertFalse(isHandleClosed(handle));
+        assertFalse(isHandleClosed(dup.getHandle()));
+
+        mem.close();
+        assertTrue(isHandleClosed(handle));
+        assertFalse(isHandleClosed(dup.getHandle()));
+    }
+
+    @Test
+    public void testDupNullHandle() throws IOException {
+        HidlMemory mem = new HidlMemory("some name", 123, null);
+
+        HidlMemory dup = mem.dup();
+        assertEquals("some name", dup.getName());
+        assertEquals(123, dup.getSize());
+        assertTrue(dup.getHandle() == null);
+    }
+
+    private static boolean isHandleClosed(NativeHandle handle) {
+        // There is no API for actually checking whether a handle is closed, and since it is a
+        // final class we can't use Mockito.spy() on it, so we rely on it throwing when trying to
+        // use it after closing.
+        try {
+            handle.getFileDescriptors();
+            return false;
+        } catch (IllegalStateException e) {
+            return true;
+        }
+    }
+}
diff --git a/tests/tests/packagewatchdog/Android.bp b/tests/tests/packagewatchdog/Android.bp
index df59195..8773e4a 100644
--- a/tests/tests/packagewatchdog/Android.bp
+++ b/tests/tests/packagewatchdog/Android.bp
@@ -23,6 +23,7 @@
         "vts",
         "vts10",
         "general-tests",
+        "mts"
     ],
     libs: ["android.test.base.stubs"],
     static_libs: [
diff --git a/tests/tests/permission/src/android/permission/cts/PermissionControllerTest.java b/tests/tests/permission/src/android/permission/cts/PermissionControllerTest.java
index 5be2710..7c23156 100644
--- a/tests/tests/permission/src/android/permission/cts/PermissionControllerTest.java
+++ b/tests/tests/permission/src/android/permission/cts/PermissionControllerTest.java
@@ -27,6 +27,7 @@
 import static android.app.AppOpsManager.MODE_FOREGROUND;
 import static android.app.AppOpsManager.permissionToOp;
 import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.permission.PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED;
 import static android.permission.PermissionControllerManager.REASON_INSTALLER_POLICY_VIOLATION;
 import static android.permission.PermissionControllerManager.REASON_MALWARE;
 import static android.permission.cts.PermissionUtils.grantPermission;
@@ -40,6 +41,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static java.util.Collections.singletonList;
+
 import android.app.AppOpsManager;
 import android.app.UiAutomation;
 import android.content.Context;
@@ -161,7 +164,7 @@
 
     private Map<String, List<String>> buildRevokeRequest(@NonNull String app,
             @NonNull String permission) {
-        return Collections.singletonMap(app, Collections.singletonList(permission));
+        return Collections.singletonMap(app, singletonList(permission));
     }
 
     private void assertRuntimePermissionLabelsAreValid(List<String> runtimePermissions,
@@ -309,7 +312,7 @@
     @Test(expected = NullPointerException.class)
     public void revokePermissionsWithNullPkg() throws Exception {
         Map<String, List<String>> request = Collections.singletonMap(null,
-                Collections.singletonList(ACCESS_FINE_LOCATION));
+                singletonList(ACCESS_FINE_LOCATION));
 
         revokePermissions(request, true);
     }
@@ -324,7 +327,7 @@
     @Test(expected = NullPointerException.class)
     public void revokePermissionsWithNullPermission() throws Exception {
         Map<String, List<String>> request = Collections.singletonMap(APP,
-                Collections.singletonList(null));
+                singletonList(null));
 
         revokePermissions(request, true);
     }
@@ -474,4 +477,37 @@
     public void revokePermissionWithNullPermission() throws Exception {
         sController.revokeRuntimePermission(APP2, null);
     }
+
+    // TODO: Add more tests for countPermissionAppsGranted when the method can be safely called
+    //       multiple times in a row
+
+    @Test
+    public void countPermissionAppsGranted() {
+        runWithShellPermissionIdentity(
+                () -> {
+                    CompletableFuture<Integer> numApps = new CompletableFuture<>();
+
+                    sController.countPermissionApps(singletonList(ACCESS_FINE_LOCATION),
+                            COUNT_ONLY_WHEN_GRANTED, numApps::complete, null);
+
+                    // TODO: Better would be to count before, grant a permission, count again and
+                    //       then compare before and after
+                    assertThat(numApps.get()).isAtLeast(1);
+                });
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void countPermissionAppsNullPermission() {
+        sController.countPermissionApps(null, 0, (n) -> { }, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void countPermissionAppsInvalidFlags() {
+        sController.countPermissionApps(singletonList(ACCESS_FINE_LOCATION), -1, (n) -> { }, null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void countPermissionAppsNullCallback() {
+        sController.countPermissionApps(singletonList(ACCESS_FINE_LOCATION), 0, null, null);
+    }
 }
diff --git a/tests/tests/permission/src/android/permission/cts/ProviderPermissionTest.java b/tests/tests/permission/src/android/permission/cts/ProviderPermissionTest.java
index 78e82ff..fd72e77 100644
--- a/tests/tests/permission/src/android/permission/cts/ProviderPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/ProviderPermissionTest.java
@@ -261,7 +261,7 @@
                     ui.adoptShellPermissionIdentity("android.permission.GET_RUNTIME_PERMISSIONS");
                     try {
                         flags = pm.getPermissionFlags(WRITE_EXTERNAL_STORAGE, pkg.packageName,
-                                UserHandle.SYSTEM);
+                                android.os.Process.myUserHandle());
                     } finally {
                         ui.dropShellPermissionIdentity();
                     }
diff --git a/tests/tests/role/Android.bp b/tests/tests/role/Android.bp
index ac70a58..bb35032 100644
--- a/tests/tests/role/Android.bp
+++ b/tests/tests/role/Android.bp
@@ -18,6 +18,7 @@
 
     srcs: [
         "src/**/*.java",
+        "src/**/*.kt",
     ],
 
     static_libs: [
diff --git a/tests/tests/role/src/android/app/role/cts/RoleControllerManagerTest.kt b/tests/tests/role/src/android/app/role/cts/RoleControllerManagerTest.kt
new file mode 100644
index 0000000..8d7353b
--- /dev/null
+++ b/tests/tests/role/src/android/app/role/cts/RoleControllerManagerTest.kt
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.role.cts
+
+import android.app.Instrumentation
+
+import android.app.role.RoleControllerManager
+import android.app.role.RoleManager
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.os.Process
+import android.provider.Settings
+import androidx.test.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.TimeUnit
+import java.util.function.Consumer
+
+/**
+ * Tests [RoleControllerManager].
+ */
+@RunWith(AndroidJUnit4::class)
+class RoleControllerManagerTest {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val context: Context = instrumentation.context
+    private val packageManager: PackageManager = context.packageManager
+    private val roleControllerManager: RoleControllerManager =
+        context.getSystemService(RoleControllerManager::class.java)!!
+
+    @Before
+    fun installApp() {
+        installPackage(APP_APK_PATH)
+    }
+
+    @After
+    fun uninstallApp() {
+        uninstallPackage(APP_PACKAGE_NAME)
+    }
+
+    @Test
+    fun appIsVisibleForRole() {
+        assertAppIsVisibleForRole(APP_PACKAGE_NAME, ROLE_NAME, true)
+    }
+
+    @Test
+    fun settingsIsNotVisibleForHomeRole() {
+        // Settings should never show as a possible home app even if qualified.
+        val settingsPackageName = packageManager.resolveActivity(
+            Intent(Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY
+            or PackageManager.MATCH_DIRECT_BOOT_AWARE or PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+        )!!.activityInfo.packageName
+        assertAppIsVisibleForRole(settingsPackageName, RoleManager.ROLE_HOME, false)
+    }
+
+    @Test
+    fun appIsNotVisibleForInvalidRole() {
+        assertAppIsVisibleForRole(APP_PACKAGE_NAME, "invalid", false)
+    }
+
+    @Test
+    fun invalidAppIsNotVisibleForRole() {
+        assertAppIsVisibleForRole("invalid", ROLE_NAME, false)
+    }
+
+    private fun assertAppIsVisibleForRole(
+        packageName: String,
+        roleName: String,
+        expectedIsVisible: Boolean
+    ) {
+        val future = CompletableFuture<Boolean>()
+        runWithShellPermissionIdentity {
+            roleControllerManager.isApplicationVisibleForRole(
+                roleName, packageName, context.mainExecutor, Consumer { future.complete(it) }
+            )
+        }
+        val isVisible = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+        assertThat(isVisible).isEqualTo(expectedIsVisible)
+    }
+
+    @Test
+    fun roleIsVisible() {
+        assertRoleIsVisible(ROLE_NAME, true)
+    }
+
+    @Test
+    fun systemGalleryRoleIsNotVisible() {
+        // The system gallery role should always be hidden.
+        assertRoleIsVisible(SYSTEM_GALLERY_ROLE_NAME, false)
+    }
+
+    @Test
+    fun invalidRoleIsNotVisible() {
+        assertRoleIsVisible("invalid", false)
+    }
+
+    private fun assertRoleIsVisible(roleName: String, expectedIsVisible: Boolean) {
+        val future = CompletableFuture<Boolean>()
+        runWithShellPermissionIdentity {
+            roleControllerManager.isRoleVisible(
+                roleName, context.mainExecutor, Consumer {
+                    future.complete(it)
+                }
+            )
+        }
+        val isVisible = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+        assertThat(isVisible).isEqualTo(expectedIsVisible)
+    }
+
+    private fun installPackage(apkPath: String) {
+        assertEquals(
+            "Success",
+            runShellCommand("pm install -r --user ${Process.myUserHandle().identifier} $apkPath")
+                .trim()
+        )
+    }
+
+    private fun uninstallPackage(packageName: String) {
+        assertEquals(
+            "Success",
+            runShellCommand("pm uninstall --user ${Process.myUserHandle().identifier} $packageName")
+                .trim()
+        )
+    }
+
+    companion object {
+        private const val ROLE_NAME = RoleManager.ROLE_BROWSER
+        private const val APP_APK_PATH = "/data/local/tmp/cts/role/CtsRoleTestApp.apk"
+        private const val APP_PACKAGE_NAME = "android.app.role.cts.app"
+        private const val SYSTEM_GALLERY_ROLE_NAME = "android.app.role.SYSTEM_GALLERY"
+        private const val TIMEOUT_MILLIS = 15 * 1000L
+    }
+}
diff --git a/tests/tests/security/res/raw/bug_110435401.mid b/tests/tests/security/res/raw/bug_110435401.mid
new file mode 100644
index 0000000..184ab1f
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_110435401.mid
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_26366256.midi b/tests/tests/security/res/raw/bug_26366256.midi
deleted file mode 100644
index 5114d92..0000000
--- a/tests/tests/security/res/raw/bug_26366256.midi
+++ /dev/null
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_68664359.mid b/tests/tests/security/res/raw/bug_68664359.mid
new file mode 100644
index 0000000..f816d82
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_68664359.mid
@@ -0,0 +1 @@
+DK:@~kkkkk
\ No newline at end of file
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index e40bd6b..3720d17 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -307,12 +307,6 @@
     }
 
     @Test
-    @SecurityTest(minPatchLevel = "2016-04")
-    public void testStagefright_bug_26366256() throws Exception {
-        doStagefrightTest(R.raw.bug_26366256);
-    }
-
-    @Test
     @SecurityTest(minPatchLevel = "2017-02")
     public void testStagefright_cve_2016_2429_b_27211885() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2429_b_27211885,
@@ -1122,6 +1116,18 @@
     }
 
     @Test
+    @SecurityTest(minPatchLevel = "2018-11")
+    public void testStagefright_bug_68664359() throws Exception {
+        doStagefrightTest(R.raw.bug_68664359, 60000);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-11")
+    public void testStagefright_bug_110435401() throws Exception {
+        doStagefrightTest(R.raw.bug_110435401, 60000);
+    }
+
+    @Test
     @SecurityTest(minPatchLevel = "2017-03")
     public void testStagefright_cve_2017_0474() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0474, 120000);
diff --git a/tests/tests/telecom/src/android/telecom/cts/TelecomAvailabilityTest.java b/tests/tests/telecom/src/android/telecom/cts/TelecomAvailabilityTest.java
index 8163520..d218da9c 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TelecomAvailabilityTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TelecomAvailabilityTest.java
@@ -118,6 +118,26 @@
     }
 
     /**
+     * Tests that TelecomManager always creates resolvable/actionable emergency dialer intent.
+     */
+    public void testCreateLaunchEmergencyDialerIntent() {
+        if (!shouldTestTelecom(mContext)) {
+            return;
+        }
+        final TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
+
+        final Intent intentWithoutNumber = telecomManager.createLaunchEmergencyDialerIntent(null);
+        assertNotNull(intentWithoutNumber);
+        assertEquals(1, mPackageManager.queryIntentActivities(intentWithoutNumber,
+                PackageManager.MATCH_DEFAULT_ONLY).size());
+
+        final Intent intentWithNumber = telecomManager.createLaunchEmergencyDialerIntent("12345");
+        assertNotNull(intentWithNumber);
+        assertEquals(1, mPackageManager.queryIntentActivities(intentWithNumber,
+                PackageManager.MATCH_DEFAULT_ONLY).size());
+    }
+
+    /**
      * @return The {@link PackageInfo} of the only app named {@code PACKAGE_NAME}.
      */
     private static PackageInfo findOnlyTelecomPackageInfo(PackageManager packageManager) {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index 0fbfdd1..2dfff4f 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -2506,6 +2506,28 @@
     }
 
     @Test
+    public void testIsIccLockEnabled() {
+        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            return;
+        }
+        // verify SecurityException
+        try {
+            mTelephonyManager.isIccLockEnabled();
+            fail("testIsIccLockEnabled: Expected SecurityException on isIccLockEnabled");
+        } catch (SecurityException se) {
+            // expected
+        }
+
+        // test with permission
+        try {
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.isIccLockEnabled());
+        } catch (SecurityException se) {
+            fail("testIsIccLockEnabled: SecurityException not expected");
+        }
+    }
+
+    @Test
     public void testIsDataEnabledForApn() {
         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
             return;
@@ -2528,6 +2550,29 @@
     }
 
     @Test
+    public void testIsTetheringApnRequired() {
+        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            return;
+        }
+        // verify SecurityException
+        try {
+            mTelephonyManager.isTetheringApnRequired();
+            fail("testIsTetheringApnRequired: Expected SecurityException on "
+                    + "isTetheringApnRequired");
+        } catch (SecurityException se) {
+            // expected
+        }
+
+        // test with permission
+        try {
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.isTetheringApnRequired());
+        } catch (SecurityException se) {
+            fail("testIsIccLockEnabled: SecurityException not expected");
+        }
+    }
+
+    @Test
     public void testGetCarrierInfoForImsiEncryption() {
         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
             return;
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerFilterTest.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerFilterTest.java
new file mode 100644
index 0000000..4e019b1
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerFilterTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.media.tv.tuner.Tuner;
+import android.media.tv.tuner.filter.AlpFilterConfiguration;
+import android.media.tv.tuner.filter.AvSettings;
+import android.media.tv.tuner.filter.DownloadSettings;
+import android.media.tv.tuner.filter.Filter;
+import android.media.tv.tuner.filter.IpFilterConfiguration;
+import android.media.tv.tuner.filter.MmtpFilterConfiguration;
+import android.media.tv.tuner.filter.PesSettings;
+import android.media.tv.tuner.filter.RecordSettings;
+import android.media.tv.tuner.filter.SectionSettingsWithSectionBits;
+import android.media.tv.tuner.filter.SectionSettingsWithTableInfo;
+import android.media.tv.tuner.filter.TlvFilterConfiguration;
+import android.media.tv.tuner.filter.TsFilterConfiguration;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class TunerFilterTest {
+    private static final String TAG = "MediaTunerFilterTest";
+
+    private Context mContext;
+    private Tuner mTuner;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+        InstrumentationRegistry
+                .getInstrumentation().getUiAutomation().adoptShellPermissionIdentity();
+        if (!hasTuner()) return;
+        mTuner = new Tuner(mContext, null, 100);
+    }
+
+    @After
+    public void tearDown() {
+        if (mTuner != null) {
+          mTuner.close();
+          mTuner = null;
+        }
+    }
+
+    @Test
+    public void testAvSettings() throws Exception {
+        if (!hasTuner()) return;
+        AvSettings settings =
+                AvSettings
+                        .builder(Filter.TYPE_TS, true)
+                        .setPassthrough(false)
+                        .build();
+
+        assertFalse(settings.isPassthrough());
+    }
+
+    @Test
+    public void testDownloadSettings() throws Exception {
+        if (!hasTuner()) return;
+        DownloadSettings settings =
+                DownloadSettings
+                        .builder(Filter.TYPE_MMTP)
+                        .setDownloadId(2)
+                        .build();
+
+        assertEquals(2, settings.getDownloadId());
+    }
+
+    @Test
+    public void testPesSettings() throws Exception {
+        if (!hasTuner()) return;
+        PesSettings settings =
+                PesSettings
+                        .builder(Filter.TYPE_TS)
+                        .setStreamId(2)
+                        .setRaw(true)
+                        .build();
+
+        assertEquals(2, settings.getStreamId());
+        assertTrue(settings.isRaw());
+    }
+
+    @Test
+    public void testRecordSettings() throws Exception {
+        if (!hasTuner()) return;
+        RecordSettings settings =
+                RecordSettings
+                        .builder(Filter.TYPE_TS)
+                        .setTsIndexMask(
+                                RecordSettings.TS_INDEX_FIRST_PACKET
+                                        | RecordSettings.TS_INDEX_PRIVATE_DATA)
+                        .setScIndexType(RecordSettings.INDEX_TYPE_SC)
+                        .setScIndexMask(RecordSettings.SC_INDEX_I_FRAME)
+                        .build();
+
+        assertEquals(
+                RecordSettings.TS_INDEX_FIRST_PACKET | RecordSettings.TS_INDEX_PRIVATE_DATA,
+                settings.getTsIndexMask());
+        assertEquals(RecordSettings.INDEX_TYPE_SC, settings.getScIndexType());
+        assertEquals(RecordSettings.SC_INDEX_I_FRAME, settings.getScIndexMask());
+    }
+
+    @Test
+    public void testSectionSettingsWithSectionBits() throws Exception {
+        if (!hasTuner()) return;
+        SectionSettingsWithSectionBits settings =
+                SectionSettingsWithSectionBits
+                        .builder(Filter.TYPE_TS)
+                        .setCrcEnabled(true)
+                        .setRepeat(false)
+                        .setRaw(false)
+                        .setFilter(new byte[] {2, 3, 4})
+                        .setMask(new byte[] {7, 6, 5, 4})
+                        .setMode(new byte[] {22, 55, 33})
+                        .build();
+
+        assertTrue(settings.isCrcEnabled());
+        assertFalse(settings.isRepeat());
+        assertFalse(settings.isRaw());
+        Assert.assertArrayEquals(new byte[] {2, 3, 4}, settings.getFilterBytes());
+        Assert.assertArrayEquals(new byte[] {7, 6, 5, 4}, settings.getMask());
+        Assert.assertArrayEquals(new byte[] {22, 55, 33}, settings.getMode());
+    }
+
+    @Test
+    public void testSectionSettingsWithTableInfo() throws Exception {
+        if (!hasTuner()) return;
+        SectionSettingsWithTableInfo settings =
+                SectionSettingsWithTableInfo
+                        .builder(Filter.TYPE_TS)
+                        .setTableId(11)
+                        .setVersion(2)
+                        .setCrcEnabled(false)
+                        .setRepeat(true)
+                        .setRaw(true)
+                        .build();
+
+        assertEquals(11, settings.getTableId());
+        assertEquals(2, settings.getVersion());
+        assertFalse(settings.isCrcEnabled());
+        assertTrue(settings.isRepeat());
+        assertTrue(settings.isRaw());
+    }
+
+    @Test
+    public void testAlpFilterConfiguration() throws Exception {
+        if (!hasTuner()) return;
+        AlpFilterConfiguration config =
+                AlpFilterConfiguration
+                        .builder()
+                        .setPacketType(AlpFilterConfiguration.PACKET_TYPE_COMPRESSED)
+                        .setLengthType(AlpFilterConfiguration.LENGTH_TYPE_WITH_ADDITIONAL_HEADER)
+                        .build();
+
+        assertEquals(Filter.TYPE_ALP, config.getType());
+        assertEquals(AlpFilterConfiguration.PACKET_TYPE_COMPRESSED, config.getPacketType());
+        assertEquals(
+                AlpFilterConfiguration.LENGTH_TYPE_WITH_ADDITIONAL_HEADER, config.getLengthType());
+    }
+
+    @Test
+    public void testIpFilterConfiguration() throws Exception {
+        if (!hasTuner()) return;
+        IpFilterConfiguration config =
+                IpFilterConfiguration
+                        .builder()
+                        .setSrcIpAddress(new byte[] {(byte) 0xC0, (byte) 0xA8, 0, 1})
+                        .setDstIpAddress(new byte[] {(byte) 0xC0, (byte) 0xA8, 3, 4})
+                        .setSrcPort(33)
+                        .setDstPort(23)
+                        .setPassthrough(false)
+                        .build();
+
+        assertEquals(Filter.TYPE_IP, config.getType());
+        Assert.assertArrayEquals(new byte[] {(byte) 0xC0, (byte) 0xA8, 0, 1}, config.getSrcIpAddress());
+        Assert.assertArrayEquals(new byte[] {(byte) 0xC0, (byte) 0xA8, 3, 4}, config.getDstIpAddress());
+        assertEquals(33, config.getSrcPort());
+        assertEquals(23, config.getDstPort());
+        assertFalse(config.isPassthrough());
+    }
+
+    @Test
+    public void testMmtpFilterConfiguration() throws Exception {
+        if (!hasTuner()) return;
+        MmtpFilterConfiguration config =
+                MmtpFilterConfiguration
+                        .builder()
+                        .setMmtpPacketId(3)
+                        .build();
+
+        assertEquals(Filter.TYPE_MMTP, config.getType());
+        assertEquals(3, config.getMmtpPacketId());
+    }
+
+    @Test
+    public void testTlvFilterConfiguration() throws Exception {
+        if (!hasTuner()) return;
+        TlvFilterConfiguration config =
+                TlvFilterConfiguration
+                        .builder()
+                        .setPacketType(TlvFilterConfiguration.PACKET_TYPE_IPV4)
+                        .setCompressedIpPacket(true)
+                        .setPassthrough(false)
+                        .build();
+
+        assertEquals(Filter.TYPE_TLV, config.getType());
+        assertEquals(TlvFilterConfiguration.PACKET_TYPE_IPV4, config.getPacketType());
+        assertTrue(config.isCompressedIpPacket());
+        assertFalse(config.isPassthrough());
+    }
+
+    @Test
+    public void testTsFilterConfiguration() throws Exception {
+        if (!hasTuner()) return;
+
+        PesSettings settings =
+                PesSettings
+                        .builder(Filter.TYPE_TS)
+                        .setStreamId(3)
+                        .setRaw(false)
+                        .build();
+
+        TsFilterConfiguration config =
+                TsFilterConfiguration
+                        .builder()
+                        .setTpid(521)
+                        .setSettings(settings)
+                        .build();
+
+        assertEquals(Filter.TYPE_TS, config.getType());
+        assertEquals(521, config.getTpid());
+
+        assertTrue(config.getSettings() instanceof PesSettings);
+        PesSettings pes = (PesSettings) config.getSettings();
+        assertEquals(3, pes.getStreamId());
+        assertFalse(pes.isRaw());
+    }
+
+
+    private boolean hasTuner() {
+        return mContext.getPackageManager().hasSystemFeature("android.hardware.tv.tuner");
+    }
+}