Merge "ITS: test_sensor_fusion.py --> set max exposure to reduce motion blur" into sc-dev
diff --git a/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py b/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py
index 6e9ee5d..e666763 100644
--- a/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py
+++ b/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py
@@ -41,7 +41,7 @@
         camera_id=self.camera_id) as cam:
 
       camera_properties_utils.skip_unless(
-          cam.is_s_performance_class_primary_camera())
+          cam.is_performance_class_primary_camera())
 
       # Load chart for scene.
       props = cam.get_camera_properties()
diff --git a/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py b/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py
index 2fe7175..ba4867b 100644
--- a/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py
+++ b/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py
@@ -41,7 +41,7 @@
         camera_id=self.camera_id) as cam:
 
       camera_properties_utils.skip_unless(
-          cam.is_s_performance_class_primary_camera())
+          cam.is_performance_class_primary_camera())
 
       # Load chart for scene.
       props = cam.get_camera_properties()
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index 1155fc9..4cd9e2d 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -1075,8 +1075,8 @@
                                       ' support')
     return data['strValue'] == 'true'
 
-  def is_s_performance_class_primary_camera(self):
-    """Query whether the camera device is a S performance class primary camera.
+  def is_performance_class_primary_camera(self):
+    """Query whether the camera device is an R or S performance class primary camera.
 
     A primary rear/front facing camera is a camera device with the lowest
     camera Id for that facing.
@@ -1085,13 +1085,13 @@
       Boolean
     """
     cmd = {}
-    cmd['cmdName'] = 'isSPerformanceClassPrimaryCamera'
+    cmd['cmdName'] = 'isPerformanceClassPrimaryCamera'
     cmd['cameraId'] = self._camera_id
     self.sock.send(json.dumps(cmd).encode() + '\n'.encode())
 
     data, _ = self.__read_response_from_socket()
-    if data['tag'] != 'sPerformanceClassPrimaryCamera':
-      raise error_util.CameraItsError('Failed to query S performance class '
+    if data['tag'] != 'performanceClassPrimaryCamera':
+      raise error_util.CameraItsError('Failed to query performance class '
                                       'primary camera')
     return data['strValue'] == 'true'
 
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 807a5a0..f51141a 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -94,6 +94,9 @@
          removed once tests are refactored to use the proper IPC between theses users.  -->
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
 
+    <!-- Needed for sensor tests -->
+    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
+
     <application>
 
         <meta-data android:name="SuiteName" android:value="CTS_VERIFIER" />
@@ -4577,6 +4580,21 @@
                        android:value="multi_display_mode" />
         </activity>
 
+        <activity android:name=".tv.display.ModeSwitchingTestActivity"
+                  android:label="@string/tv_mode_switching_test"
+                  android:exported="true"
+                  android:configChanges="orientation|screenSize|density|smallestScreenSize|screenLayout">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_tv"/>
+            <meta-data android:name="test_required_features"
+                       android:value="android.software.leanback"/>
+            <meta-data android:name="display_mode"
+                       android:value="multi_display_mode" />
+        </activity>
+
         <activity android:name=".screenpinning.ScreenPinningTestActivity"
                 android:exported="true"
             android:label="@string/screen_pinning_test">
diff --git a/apps/CtsVerifier/res/layout/policy_transparency_test.xml b/apps/CtsVerifier/res/layout/policy_transparency_test.xml
index 131ff3e..f2a1226 100644
--- a/apps/CtsVerifier/res/layout/policy_transparency_test.xml
+++ b/apps/CtsVerifier/res/layout/policy_transparency_test.xml
@@ -19,7 +19,8 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:descendantFocusability="beforeDescendants"
-        android:focusableInTouchMode="true">
+        android:focusableInTouchMode="true"
+        android:nextFocusDown="@+id/switch_widget">
     <ScrollView
             android:layout_width="match_parent"
             android:layout_height="0dp"
@@ -51,31 +52,36 @@
                 android:layout_height="wrap_content"
                 android:paddingStart="8dp"
                 android:paddingEnd="16dp"
-                android:visibility="gone" />
+                android:visibility="gone"
+                android:nextFocusDown="@+id/edit_text_widget"/>
         <EditText android:id="@+id/edit_text_widget"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:ems="6"
                 android:singleLine="true"
                 android:gravity="center"
-                android:visibility="gone" />
+                android:visibility="gone"
+                android:nextFocusDown="@+id/update_button"/>
         <Button android:id="@+id/update_button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:text="@string/policy_transparency_update_button_label"
                 android:paddingStart="8dp"
                 android:paddingEnd="16dp"
-                android:visibility="gone" />
+                android:visibility="gone"
+                android:nextFocusDown="@+id/spinner_widget"/>
         <Spinner android:id="@+id/spinner_widget"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:visibility="gone" />
+                android:visibility="gone"
+                android:nextFocusDown="@+id/open_settings_button"/>
     </LinearLayout>
 
     <Button android:id="@+id/open_settings_button"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:text="@string/policy_transparency_open_settings_label" />
+            android:text="@string/policy_transparency_open_settings_label"
+            android:nextFocusUp="@+id/switch_widget"/>
 
     <include layout="@layout/pass_fail_buttons"/>
 </LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/tv_instructions_and_video.xml b/apps/CtsVerifier/res/layout/tv_instructions_and_video.xml
new file mode 100644
index 0000000..d7dfe16
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/tv_instructions_and_video.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingLeft="50px"
+    android:paddingRight="50px">
+
+    <FrameLayout
+        android:id="@+id/instructions"
+        android:layout_width="match_parent"
+        android:layout_height="0px"
+        android:layout_weight="1">
+        <LinearLayout
+            android:id="@+id/test_items"
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+        </LinearLayout>
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/videoframe"
+        android:layout_width="match_parent"
+        android:layout_height="0px"
+        android:layout_weight="2">
+        <SurfaceView
+            android:id="@+id/surface"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="center">
+        </SurfaceView>
+    </FrameLayout>
+
+    <include layout="@layout/pass_fail_buttons"/>
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/tv_item.xml b/apps/CtsVerifier/res/layout/tv_item.xml
index e2756ec..21334d9 100644
--- a/apps/CtsVerifier/res/layout/tv_item.xml
+++ b/apps/CtsVerifier/res/layout/tv_item.xml
@@ -55,7 +55,6 @@
         android:layout_height="wrap_content"
         android:id="@+id/loadingSpinner"
         android:layout_centerInParent="true"
-        android:layout_alignParentBottom="true"
         android:visibility="invisible"/>
 
 </RelativeLayout>
diff --git a/apps/CtsVerifier/res/raw/bunny_1280x720_24fps_VP9.webm b/apps/CtsVerifier/res/raw/bunny_1280x720_24fps_VP9.webm
new file mode 100644
index 0000000..512e1f0
--- /dev/null
+++ b/apps/CtsVerifier/res/raw/bunny_1280x720_24fps_VP9.webm
Binary files differ
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index fe13cfe..e3358bd 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -4802,6 +4802,23 @@
         cable again.
     </string>
 
+    <!-- Mode Switching Test -->
+    <string name="tv_mode_switching_test">Mode switching test</string>
+    <string name="tv_mode_switching_test_step_instruction">
+        Click "Start Test" and then observe the video below. Testing transition from %1$s to %2$s.
+    </string>
+    <string name="tv_mode_switching_test_black_screen_question">
+        Did the video playback experience an interruption, for example, a black or solid color
+        screen?
+    </string>
+    <string name="tv_mode_switching_test_is_video_ok">
+        Does the video look okay? Click "No" if the video is not playing, there was a snow screen,
+        audio static, wrong colors, the video is displaced compared to before running the test or
+        if the video is not playing. Keep in mind that some stutter is expected when the video does
+        not match the refresh rate.
+    </string>
+    <string name="tv_mode_switching_test_mode_switch_step">Mode switch step</string>
+
     <string name="overlay_view_text">Overlay View Dummy Text</string>
     <string name="custom_rating">Example of input app specific custom rating.</string>
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleCocClientService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleCocClientService.java
index 183cebd..9d4c7a9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleCocClientService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleCocClientService.java
@@ -217,7 +217,6 @@
                     break;
                 case BLE_COC_CLIENT_ACTION_EXCHANGE_DATA:
                     sendDataLargeBuf();
-                    readDataLargeBuf();
                     break;
                 case BLE_CLIENT_ACTION_CLIENT_DISCONNECT:
                     if (mBluetoothGatt != null) {
@@ -546,9 +545,16 @@
             }
             Intent intent = new Intent(mNextReadCompletionIntent);
             sendBroadcast(intent);
-            mNextReadExpectedLen = -1;
-            mNextReadCompletionIntent = null;
             mTotalReadLen = 0;
+            if (mNextReadCompletionIntent.equals(BLE_DATA_8BYTES_READ)) {
+                // The server will not wait for any signal to send out the next bunch of data, after
+                // it finishes sending the first 8 bytes. That means if we set the expectation
+                // asynchronously, the data could come before that, so we have to do that here.
+                readDataLargeBuf();
+            } else {
+                mNextReadExpectedLen = -1;
+                mNextReadCompletionIntent = null;
+            }
         } else if (mNextReadExpectedLen > mTotalReadLen) {
             if (!checkReadBufContent(buf, len)) {
                 mNextReadExpectedLen = -1;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleCocServerService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleCocServerService.java
index 6dc84f2..829f540 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleCocServerService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleCocServerService.java
@@ -309,7 +309,6 @@
                     break;
                 case BLE_COC_SERVER_ACTION_EXCHANGE_DATA:
                     sendDataLargeBuf();
-                    readDataLargeBuf();
                     break;
                 case BLE_COC_SERVER_ACTION_DISCONNECT:
                     if (mChatService != null) {
@@ -610,9 +609,15 @@
             }
             Intent intent = new Intent(mNextReadCompletionIntent);
             sendBroadcast(intent);
-            mNextReadExpectedLen = -1;
-            mNextReadCompletionIntent = null;
             mTotalReadLen = 0;
+            if (mNextReadCompletionIntent.equals(BLE_DATA_8BYTES_READ)) {
+                // Keeps the logic same as in the client code, to make sure that the expectation is
+                // set before we receive the next bunch of data.
+                readDataLargeBuf();
+            } else {
+                mNextReadExpectedLen = -1;
+                mNextReadCompletionIntent = null;
+            }
         } else if (mNextReadExpectedLen > mTotalReadLen) {
             if (!checkReadBufContent(buf, len)) {
                 mNextReadExpectedLen = -1;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index 10775fe..63d9687 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -148,6 +148,8 @@
     // Supports at most RAW+YUV+JPEG, one surface each, plus optional background stream
     private static final int MAX_NUM_OUTPUT_SURFACES = 4;
 
+    // Performance class R version number
+    private static final int PERFORMANCE_CLASS_R = Build.VERSION_CODES.R;
     // Performance class S version number
     private static final int PERFORMANCE_CLASS_S = Build.VERSION_CODES.R + 1;
 
@@ -735,9 +737,9 @@
                     doCheckStreamCombination(cmdObj);
                 } else if ("isCameraPrivacyModeSupported".equals(cmdObj.getString("cmdName"))) {
                     doCheckCameraPrivacyModeSupport();
-                } else if ("isSPerformanceClassPrimaryCamera".equals(cmdObj.getString("cmdName"))) {
+                } else if ("isPerformanceClassPrimaryCamera".equals(cmdObj.getString("cmdName"))) {
                     String cameraId = cmdObj.getString("cameraId");
-                    doCheckSPerformanceClassPrimaryCamera(cameraId);
+                    doCheckPerformanceClassPrimaryCamera(cameraId);
                 } else if ("measureCameraLaunchMs".equals(cmdObj.getString("cmdName"))) {
                     String cameraId = cmdObj.getString("cameraId");
                     doMeasureCameraLaunchMs(cameraId);
@@ -1080,8 +1082,9 @@
                 hasPrivacySupport ? "true" : "false");
     }
 
-    private void doCheckSPerformanceClassPrimaryCamera(String cameraId) throws ItsException {
-        boolean  isSPerfClass = (Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_S);
+    private void doCheckPerformanceClassPrimaryCamera(String cameraId) throws ItsException {
+        boolean  isPerfClass = (Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_S
+                || Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_R);
 
         if (mItsCameraIdList == null) {
             mItsCameraIdList = ItsUtils.getItsCompatibleCameraIds(mCameraManager);
@@ -1113,8 +1116,8 @@
             throw new ItsException("Failed to get camera characteristics", e);
         }
 
-        mSocketRunnableObj.sendResponse("sPerformanceClassPrimaryCamera",
-                (isSPerfClass && isPrimaryCamera) ? "true" : "false");
+        mSocketRunnableObj.sendResponse("performanceClassPrimaryCamera",
+                (isPerfClass && isPrimaryCamera) ? "true" : "false");
     }
 
     private double invokeCameraPerformanceTest(Class testClass, String testName,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java
index d99672d..055f26f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java
@@ -1,7 +1,5 @@
 package com.android.cts.verifier.tunnelmode;
 
-import android.app.Activity;
-import android.content.res.Resources;
 import android.media.AudioManager;
 import android.media.cts.MediaCodecTunneledPlayer;
 import android.net.Uri;
@@ -58,7 +56,7 @@
         AudioManager am = (AudioManager) getApplicationContext().getSystemService(AUDIO_SERVICE);
         mAudioSessionId = am.generateAudioSessionId();
 
-        mPlayer = new MediaCodecTunneledPlayer(mHolder, true, mAudioSessionId);
+        mPlayer = new MediaCodecTunneledPlayer(this, mHolder, true, mAudioSessionId);
 
         // TODO: Do not rely on the video being pre-loaded on the device
         Uri mediaUri = Uri.fromFile(new File("/data/local/tmp/video.webm"));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/AppLinkTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/AppLinkTestActivity.java
index 3e8790b..658a5fd 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/AppLinkTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/AppLinkTestActivity.java
@@ -104,17 +104,18 @@
 
     @Override
     protected void createTestItems() {
-        mSupportThirdPartyInputYesItem = createUserItem(
+        mSupportThirdPartyInputYesItem = createAndAttachUserItem(
                 R.string.tv_input_discover_test_third_party_tif_input_support,
                 R.string.tv_yes, this);
         setButtonEnabled(mSupportThirdPartyInputYesItem, true);
-        mSupportThirdPartyInputNoItem = createButtonItem(R.string.tv_no, this);
+        mSupportThirdPartyInputNoItem = createAndAttachButtonItem(R.string.tv_no, this);
         setButtonEnabled(mSupportThirdPartyInputNoItem, true);
-        mSelectAppLinkItem = createUserItem(R.string.tv_app_link_test_select_app_link,
+        mSelectAppLinkItem = createAndAttachUserItem(R.string.tv_app_link_test_select_app_link,
                 R.string.tv_launch_tv_app, this);
-        mVerifyAppLinkIntentItem = createAutoItem(
+        mVerifyAppLinkIntentItem = createAndAttachAutoItem(
                 R.string.tv_app_link_test_verify_link_clicked);
-        mVerifyAppLinkCardItem = createUserItem(R.string.tv_input_link_test_verify_link_interface,
+        mVerifyAppLinkCardItem = createAndAttachUserItem(
+                R.string.tv_input_link_test_verify_link_interface,
                 android.R.string.yes, this);
         TextView instructions = (TextView) mVerifyAppLinkCardItem.findViewById(R.id.instructions);
         Drawable image = getDrawable(R.drawable.app_link_img);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MicrophoneDeviceTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MicrophoneDeviceTestActivity.java
index eca02c1..6c8c7d4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MicrophoneDeviceTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MicrophoneDeviceTestActivity.java
@@ -16,14 +16,9 @@
 
 package com.android.cts.verifier.tv;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.hardware.input.InputManager;
-import android.os.Bundle;
 import android.util.Log;
 import android.view.InputDevice;
 import android.view.View;
@@ -31,6 +26,10 @@
 
 import com.android.cts.verifier.R;
 
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
 /**
  * Tests for verifying that all input devices report correct hasMicrophone() states.
  */
@@ -93,11 +92,11 @@
 
     @Override
     protected void createTestItems() {
-        mPreparationYesItem = createUserItem(
+        mPreparationYesItem = createAndAttachUserItem(
                 R.string.tv_microphone_device_test_prep_question,
                 R.string.tv_yes, this);
         setButtonEnabled(mPreparationYesItem, true);
-        mPreparationNoItem = createButtonItem(R.string.tv_no, this);
+        mPreparationNoItem = createAndAttachButtonItem(R.string.tv_no, this);
         setButtonEnabled(mPreparationNoItem, true);
     }
 
@@ -123,9 +122,10 @@
             final CharSequence micQuestion =
                 getString(R.string.tv_microphone_device_test_mic_question, inputDevice.getName());
 
-            final View inputDeviceYesItem = createUserItem(micQuestion, R.string.tv_yes, this);
+            final View inputDeviceYesItem =
+                    createAndAttachUserItem(micQuestion, R.string.tv_yes, this);
             setButtonEnabled(inputDeviceYesItem, true);
-            final View inputDeviceNoItem = createButtonItem(R.string.tv_no, this);
+            final View inputDeviceNoItem = createAndAttachButtonItem(R.string.tv_no, this);
             setButtonEnabled(inputDeviceNoItem, true);
             mInputDeviceItems.put(
                 inputDeviceYesItem, Arrays.asList(true, hasMicrophone, inputDeviceNoItem));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MultipleTracksTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MultipleTracksTestActivity.java
index a31162f..343fb16 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MultipleTracksTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MultipleTracksTestActivity.java
@@ -137,24 +137,24 @@
 
     @Override
     protected void createTestItems() {
-        mSupportThirdPartyInputYesItem = createUserItem(
+        mSupportThirdPartyInputYesItem = createAndAttachUserItem(
                 R.string.tv_input_discover_test_third_party_tif_input_support,
                 R.string.tv_yes, this);
         setButtonEnabled(mSupportThirdPartyInputYesItem, true);
-        mSupportThirdPartyInputNoItem = createButtonItem(R.string.tv_no, this);
+        mSupportThirdPartyInputNoItem = createAndAttachButtonItem(R.string.tv_no, this);
         setButtonEnabled(mSupportThirdPartyInputNoItem, true);
-        mSelectSubtitleItem = createUserItem(
+        mSelectSubtitleItem = createAndAttachUserItem(
                 R.string.tv_multiple_tracks_test_select_subtitle,
                 R.string.tv_launch_tv_app, this);
-        mVerifySetCaptionEnabledItem = createAutoItem(
+        mVerifySetCaptionEnabledItem = createAndAttachAutoItem(
                 R.string.tv_multiple_tracks_test_verify_set_caption_enabled);
-        mVerifySelectSubtitleItem = createAutoItem(
+        mVerifySelectSubtitleItem = createAndAttachAutoItem(
                 R.string.tv_multiple_tracks_test_verify_select_subtitle);
-        mSelectAudioItem = createUserItem(
+        mSelectAudioItem = createAndAttachUserItem(
                 R.string.tv_multiple_tracks_test_select_audio,
                 R.string.tv_launch_tv_app, this);
         mSelectAudioItem.setTag(Integer.valueOf(0));
-        mVerifySelectAudioItem = createAutoItem(
+        mVerifySelectAudioItem = createAndAttachAutoItem(
                 R.string.tv_multiple_tracks_test_verify_select_audio);
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/ParentalControlTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/ParentalControlTestActivity.java
index 2e5711f..d17f66f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/ParentalControlTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/ParentalControlTestActivity.java
@@ -157,26 +157,26 @@
 
     @Override
     protected void createTestItems() {
-        mSupportThirdPartyInputYesItem = createUserItem(
+        mSupportThirdPartyInputYesItem = createAndAttachUserItem(
                 R.string.tv_input_discover_test_third_party_tif_input_support,
                 R.string.tv_yes, this);
         setButtonEnabled(mSupportThirdPartyInputYesItem, true);
-        mSupportThirdPartyInputNoItem = createButtonItem(R.string.tv_no, this);
+        mSupportThirdPartyInputNoItem = createAndAttachButtonItem(R.string.tv_no, this);
         setButtonEnabled(mSupportThirdPartyInputNoItem, true);
-        mParentalControlsSwitchYesItem = createUserItem(
+        mParentalControlsSwitchYesItem = createAndAttachUserItem(
                 R.string.tv_parental_control_test_check_parental_controls_switch,
                 R.string.tv_yes, this);
-        mParentalControlsSwitchNoItem = createButtonItem(R.string.tv_no, this);
-        mTurnOnParentalControlItem = createUserItem(
+        mParentalControlsSwitchNoItem = createAndAttachButtonItem(R.string.tv_no, this);
+        mTurnOnParentalControlItem = createAndAttachUserItem(
                 R.string.tv_parental_control_test_turn_on_parental_control,
                 R.string.tv_launch_tv_app, this);
-        mVerifyReceiveBroadcast1Item = createAutoItem(
+        mVerifyReceiveBroadcast1Item = createAndAttachAutoItem(
                 R.string.tv_parental_control_test_verify_receive_broadcast1);
-        mBlockTvMaItem = createUserItem(R.string.tv_parental_control_test_block_tv_ma,
+        mBlockTvMaItem = createAndAttachUserItem(R.string.tv_parental_control_test_block_tv_ma,
                 R.string.tv_launch_tv_app, this);
-        mVerifyReceiveBroadcast2Item = createAutoItem(
+        mVerifyReceiveBroadcast2Item = createAndAttachAutoItem(
                 R.string.tv_parental_control_test_verify_receive_broadcast2);
-        mBlockUnblockItem = createUserItem(R.string.tv_parental_control_test_block_unblock,
+        mBlockUnblockItem = createAndAttachUserItem(R.string.tv_parental_control_test_block_unblock,
                 R.string.tv_launch_tv_app, this);
         mTurnOnParentalControlItem.setVisibility(View.GONE);
         mVerifyReceiveBroadcast1Item.setVisibility(View.GONE);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TestSequence.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TestSequence.java
index 7b80155..bbdbbba 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TestSequence.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TestSequence.java
@@ -1,8 +1,6 @@
 package com.android.cts.verifier.tv;
 
 
-import com.android.cts.verifier.tv.TvAppVerifierActivity;
-
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -35,7 +33,9 @@
         }
 
         // Initialize all containing test steps.
-        steps.stream().forEach(step -> step.createUiElements());
+        steps.stream()
+                .flatMap(step -> step.createUiElements().stream())
+                .forEach(view -> context.addItem(view));
 
         // After a step is completed we enable the button of the next step.
         for (int i = 0; i < steps.size() - 1; i++) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TestStepBase.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TestStepBase.java
index 6c9b5a1..9c117e4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TestStepBase.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TestStepBase.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.verifier.tv;
 
+import android.app.Activity;
 import android.view.View;
 import android.widget.TextView;
 
@@ -24,9 +25,12 @@
 import com.google.common.truth.FailureStrategy;
 import com.google.common.truth.StandardSubjectBuilder;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /** Encapsulates the logic of a test step, which displays human instructions. */
 public abstract class TestStepBase {
-    protected final TvAppVerifierActivity mContext;
+    protected final Activity mContext;
 
     private boolean mHasPassed;
     private Runnable mOnDoneListener;
@@ -41,7 +45,7 @@
      * @param context The test activity which this test step is part of.
      * @param instructionText The text of the test instruction visible to the user.
      */
-    public TestStepBase(TvAppVerifierActivity context, String instructionText) {
+    public TestStepBase(Activity context, String instructionText) {
         this.mContext = context;
 
         FailureStrategy failureStrategy =
@@ -59,8 +63,12 @@
     }
 
     /** Creates the View for this test step in the context {@link TvAppVerifierActivity}. */
-    public void createUiElements() {
-        mInstructionView = mContext.createAutoItem(mInstructionText);
+    public List<View> createUiElements() {
+        mInstructionView = TvAppVerifierActivity
+                .createAutoItem(mContext.getLayoutInflater(), mInstructionText, null);
+        List<View> list = new ArrayList<>();
+        list.add(mInstructionView);
+        return list;
     }
 
     /** Enables interactivity for this test step - for example, it enables buttons. */
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TimeShiftTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TimeShiftTestActivity.java
index 41db8e7..09cef36 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TimeShiftTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TimeShiftTestActivity.java
@@ -199,32 +199,32 @@
 
     @Override
     protected void createTestItems() {
-        mSupportThirdPartyInputYesItem = createUserItem(
+        mSupportThirdPartyInputYesItem = createAndAttachUserItem(
                 R.string.tv_input_discover_test_third_party_tif_input_support,
                 R.string.tv_yes, this);
         setButtonEnabled(mSupportThirdPartyInputYesItem, true);
-        mSupportThirdPartyInputNoItem = createButtonItem(R.string.tv_no, this);
+        mSupportThirdPartyInputNoItem = createAndAttachButtonItem(R.string.tv_no, this);
         setButtonEnabled(mSupportThirdPartyInputNoItem, true);
-        mPauseResumeItem = createUserItem(
+        mPauseResumeItem = createAndAttachUserItem(
                 R.string.tv_time_shift_test_pause_resume,
                 R.string.tv_launch_tv_app, this);
-        mVerifyResumeAfterPauseItem = createAutoItem(
+        mVerifyResumeAfterPauseItem = createAndAttachAutoItem(
                 R.string.tv_time_shift_test_verify_resume_after_pause);
-        mVerifyPositionTrackingItem = createAutoItem(
+        mVerifyPositionTrackingItem = createAndAttachAutoItem(
                 R.string.tv_time_shift_test_verify_position_tracking);
-        mSetPlaybackParamsItem = createUserItem(
+        mSetPlaybackParamsItem = createAndAttachUserItem(
                 R.string.tv_time_shift_test_speed_rate,
                 R.string.tv_launch_tv_app, this);
-        mVerifyRewindItem = createAutoItem(
+        mVerifyRewindItem = createAndAttachAutoItem(
                 R.string.tv_time_shift_test_verify_rewind);
-        mVerifyFastForwardItem = createAutoItem(
+        mVerifyFastForwardItem = createAndAttachAutoItem(
                 R.string.tv_time_shift_test_verify_fast_forward);
-        mSeekToItem = createUserItem(
+        mSeekToItem = createAndAttachUserItem(
                 R.string.tv_time_shift_test_seek,
                 R.string.tv_launch_tv_app, this);
-        mVerifySeekToPreviousItem = createAutoItem(
+        mVerifySeekToPreviousItem = createAndAttachAutoItem(
                 R.string.tv_time_shift_test_verify_seek_to_previous);
-        mVerifySeekToNextItem = createAutoItem(
+        mVerifySeekToNextItem = createAndAttachAutoItem(
                 R.string.tv_time_shift_test_verify_seek_to_next);
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java
index 1c9fc0f..c65a3e0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java
@@ -78,7 +78,8 @@
     /**
      * Call this to create a test step where the user must perform some action.
      */
-    public View createUserItem(int instructionTextId, int buttonTextId, View.OnClickListener l) {
+    public View createAndAttachUserItem(int instructionTextId, int buttonTextId,
+            View.OnClickListener l) {
         View item = mInflater.inflate(R.layout.tv_item, mItemList, false);
         TextView instructions = (TextView) item.findViewById(R.id.instructions);
         instructions.setText(instructionTextId);
@@ -93,12 +94,12 @@
     /**
      * Call this to create a test step where the user must perform some action.
      */
-    public View createUserItem(CharSequence instructionCharSequence,
+    public View createAndAttachUserItem(CharSequence instructionCharSequence,
                                   int buttonTextId, View.OnClickListener l) {
         View item = mInflater.inflate(R.layout.tv_item, mItemList, false);
-        TextView instructions = (TextView) item.findViewById(R.id.instructions);
+        TextView instructions = item.findViewById(R.id.instructions);
         instructions.setText(instructionCharSequence);
-        Button button = (Button) item.findViewById(R.id.user_action_button);
+        Button button = item.findViewById(R.id.user_action_button);
         button.setVisibility(View.VISIBLE);
         button.setText(buttonTextId);
         button.setOnClickListener(l);
@@ -110,9 +111,9 @@
      * Call this to create a test step where the test automatically evaluates whether
      * an expected condition is satisfied.
      */
-    public View createAutoItem(int stringId) {
+    public View createAndAttachAutoItem(int stringId) {
         View item = mInflater.inflate(R.layout.tv_item, mItemList, false);
-        TextView instructions = (TextView) item.findViewById(R.id.instructions);
+        TextView instructions = item.findViewById(R.id.instructions);
         instructions.setText(stringId);
         mItemList.addView(item);
         return item;
@@ -122,10 +123,20 @@
      * Call this to create a test step where the test automatically evaluates whether
      * an expected condition is satisfied.
      */
-    public View createAutoItem(CharSequence instructionCharSequence) {
-        View item = mInflater.inflate(R.layout.tv_item, mItemList, false);
-        TextView instructions = (TextView) item.findViewById(R.id.instructions);
+    public static View createAutoItem(LayoutInflater inflater,
+            CharSequence instructionCharSequence, ViewGroup root) {
+        View item = inflater.inflate(R.layout.tv_item, root, false);
+        TextView instructions = item.findViewById(R.id.instructions);
         instructions.setText(instructionCharSequence);
+        return item;
+    }
+
+    /**
+     * Call this to create a test step where the test automatically evaluates whether
+     * an expected condition is satisfied, and to attach it to the activity.
+     */
+    public View createAndAttachAutoItem(CharSequence instructionCharSequence) {
+        View item = createAutoItem(mInflater, instructionCharSequence, mItemList);
         mItemList.addView(item);
         return item;
     }
@@ -133,20 +144,37 @@
     /**
      * Call this to create alternative choice for the previous test step.
      */
-    public View createButtonItem(int buttonTextId, View.OnClickListener l) {
-        View item = mInflater.inflate(R.layout.tv_item, mItemList, false);
-        Button button = (Button) item.findViewById(R.id.user_action_button);
+    public static View createButtonItem(LayoutInflater inflater, ViewGroup root, int buttonTextId,
+            View.OnClickListener l) {
+        View item = inflater.inflate(R.layout.tv_item, root, false);
+        Button button = item.findViewById(R.id.user_action_button);
         button.setVisibility(View.VISIBLE);
         button.setText(buttonTextId);
         button.setOnClickListener(l);
-        ImageView status = (ImageView) item.findViewById(R.id.status);
+        ImageView status = item.findViewById(R.id.status);
         status.setVisibility(View.INVISIBLE);
-        TextView instructions = (TextView) item.findViewById(R.id.instructions);
+        TextView instructions = item.findViewById(R.id.instructions);
         instructions.setVisibility(View.GONE);
+        return item;
+    }
+
+    /**
+     * Call this to create alternative choice for the previous test step and to attach it to the
+     * activity.
+     */
+    public View createAndAttachButtonItem(int buttonTextId, View.OnClickListener l) {
+        View item = createButtonItem(mInflater, mItemList, buttonTextId, l);
         mItemList.addView(item);
         return item;
     }
 
+    /**
+     * Adds an item to the activity.
+     */
+    public void addItem(View item) {
+        mItemList.addView(item);
+    }
+
     static boolean containsButton(View item, View button) {
         return item == null ? false : item.findViewById(R.id.user_action_button) == button;
     }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
index f1f79cf..4f68e8b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
@@ -151,31 +151,32 @@
 
     @Override
     protected void createTestItems() {
-        mSupportThirdPartyInputYesItem = createUserItem(
+        mSupportThirdPartyInputYesItem = createAndAttachUserItem(
                 R.string.tv_input_discover_test_third_party_tif_input_support,
                 R.string.tv_yes, this);
         setButtonEnabled(mSupportThirdPartyInputYesItem, true);
-        mSupportThirdPartyInputNoItem = createButtonItem(R.string.tv_no, this);
+        mSupportThirdPartyInputNoItem = createAndAttachButtonItem(R.string.tv_no, this);
         setButtonEnabled(mSupportThirdPartyInputNoItem, true);
-        mGoToSetupItem = createUserItem(R.string.tv_input_discover_test_go_to_setup,
+        mGoToSetupItem = createAndAttachUserItem(R.string.tv_input_discover_test_go_to_setup,
                 R.string.tv_launch_tv_app, this);
-        mVerifySetupItem = createAutoItem(R.string.tv_input_discover_test_verify_setup);
-        mTuneToChannelItem = createUserItem(R.string.tv_input_discover_test_tune_to_channel,
+        mVerifySetupItem = createAndAttachAutoItem(R.string.tv_input_discover_test_verify_setup);
+        mTuneToChannelItem = createAndAttachUserItem(
+                R.string.tv_input_discover_test_tune_to_channel,
                 R.string.tv_launch_tv_app, this);
-        mVerifyTuneItem = createAutoItem(R.string.tv_input_discover_test_verify_tune);
-        mVerifyOverlayViewItem = createAutoItem(
+        mVerifyTuneItem = createAndAttachAutoItem(R.string.tv_input_discover_test_verify_tune);
+        mVerifyOverlayViewItem = createAndAttachAutoItem(
                 R.string.tv_input_discover_test_verify_overlay_view);
-        mVerifyOverlayViewSizeChanged = createAutoItem(
+        mVerifyOverlayViewSizeChanged = createAndAttachAutoItem(
                 R.string.tv_input_discover_test_verify_size_changed);
-        mVerifyGlobalSearchItem = createAutoItem(
+        mVerifyGlobalSearchItem = createAndAttachAutoItem(
                 R.string.tv_input_discover_test_verify_global_search);
-        mGoToEpgItem = createUserItem(R.string.tv_input_discover_test_go_to_epg,
+        mGoToEpgItem = createAndAttachUserItem(R.string.tv_input_discover_test_go_to_epg,
                 R.string.tv_launch_epg, this);
-        mVerifyEpgItem = createUserItem(R.string.tv_input_discover_test_verify_epg,
+        mVerifyEpgItem = createAndAttachUserItem(R.string.tv_input_discover_test_verify_epg,
                 R.string.tv_yes, this);
-        mTriggerSetupItem = createUserItem(R.string.tv_input_discover_test_trigger_setup,
+        mTriggerSetupItem = createAndAttachUserItem(R.string.tv_input_discover_test_trigger_setup,
                 R.string.tv_launch_setup, this);
-        mVerifyTriggerSetupItem = createUserItem(
+        mVerifyTriggerSetupItem = createAndAttachUserItem(
                 R.string.tv_input_discover_test_verify_trigger_setup, R.string.tv_yes, this);
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/audio/AudioCapabilitiesTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/audio/AudioCapabilitiesTestActivity.java
index 91651ce..599bef2 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/audio/AudioCapabilitiesTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/audio/AudioCapabilitiesTestActivity.java
@@ -99,10 +99,10 @@
     @Override
     protected void createTestItems() {
         mSupportDolbyAtmosYesItem =
-                createUserItem(
+                createAndAttachUserItem(
                         R.string.tv_audio_capabilities_atmos_supported, R.string.tv_yes, this);
         setButtonEnabled(mSupportDolbyAtmosYesItem, true);
-        mSupportDolbyAtmosNoItem = createButtonItem(R.string.tv_no, this);
+        mSupportDolbyAtmosNoItem = createAndAttachButtonItem(R.string.tv_no, this);
         setButtonEnabled(mSupportDolbyAtmosNoItem, true);
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/audio/TestStep.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/audio/TestStep.java
index 1956380..0a41906 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/audio/TestStep.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/audio/TestStep.java
@@ -15,6 +15,7 @@
  */
 package com.android.cts.verifier.tv.audio;
 
+import android.app.Activity;
 import android.view.View;
 
 import androidx.annotation.StringRes;
@@ -22,6 +23,8 @@
 import com.android.cts.verifier.tv.TestStepBase;
 import com.android.cts.verifier.tv.TvAppVerifierActivity;
 
+import java.util.List;
+
 /** Test step containing instruction to the user and a button. */
 public abstract class TestStep extends TestStepBase {
     protected View mButtonView;
@@ -33,24 +36,27 @@
      *
      * @param context The test activity which this test step is part of.
      * @param instructionText Text of the test instruction visible to the user.
-     * @param buttonTextId Id of a string resource containing the text of the button.
+     * @param buttonStringId Id of a string resource containing the text of the button.
      */
     public TestStep(
-            TvAppVerifierActivity context, String instructionText, @StringRes int buttonStringId) {
+            Activity context, String instructionText, @StringRes int buttonStringId) {
         super(context, instructionText);
         mButtonStringId = buttonStringId;
     }
 
     /** Creates the View for this test step in the context {@link TvAppVerifierActivity}. */
     @Override
-    public void createUiElements() {
-        super.createUiElements();
+    public List<View> createUiElements() {
+        List<View> list = super.createUiElements();
         mButtonView =
-                mContext.createButtonItem(
+                TvAppVerifierActivity.createButtonItem(mContext.getLayoutInflater(),
+                        null,
                         mButtonStringId,
                         (View view) -> {
                             onButtonClickRunTest();
                         });
+        list.add(mButtonView);
+        return list;
     }
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/HotplugTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/HotplugTestActivity.java
index 034d1e5..79120b2 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/HotplugTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/HotplugTestActivity.java
@@ -148,11 +148,15 @@
         }
 
         @Override
-        public void createUiElements() {
-            super.createUiElements();
-            mDoneButtonView = mContext.createButtonItem(
+        public List<View> createUiElements() {
+            List<View> list = super.createUiElements();
+            mDoneButtonView = TvAppVerifierActivity.createButtonItem(
+                    mContext.getLayoutInflater(),
+                    null,
                     R.string.tv_done,
                     (View view) -> recordTestStateAndFinish());
+            list.add(mDoneButtonView);
+            return list;
         }
 
         @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java
new file mode 100644
index 0000000..23bf053
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.tv.display;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.hardware.display.DisplayManager;
+import android.media.AudioManager;
+import android.media.cts.MediaCodecTunneledPlayer;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Display;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.tv.TestStepBase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Test activity to verify that
+ *   1. switching display modes during video playback doesn't cause crashes or major regressions
+ *      in video quality
+ *   2. switching between modes is seamless if and only if the modes have alternative refresh rates
+ *          (see {@link Display.Mode#getAlternativeRefreshRates})
+ */
+public class ModeSwitchingTestActivity extends PassFailButtons.Activity {
+    private static final String TAG = ModeSwitchingTestActivity.class.getSimpleName();
+    private static final float REFRESH_RATE_TOLERANCE = 0.01f;
+
+    private SurfaceHolder mHolder;
+    private int mAudioSessionId = 0;
+    private MediaCodecTunneledPlayer mPlayer;
+
+    private ViewGroup mItemList;
+    private List<TestStepBase> mSteps;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.tv_instructions_and_video);
+        mItemList = findViewById(R.id.test_items);
+
+        DisplayManager displayManager = getSystemService(DisplayManager.class);
+        Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+
+        List<Display.Mode> modeList = findTestModes(display);
+
+        Display.Mode lastMode = display.getMode();
+        mSteps = new ArrayList<>();
+        for (Display.Mode mode : modeList) {
+            boolean isSeamlessSwitch = isSeamlessSwitch(lastMode, mode);
+            mSteps.addAll(createTestStepsForTransition(lastMode, mode, isSeamlessSwitch));
+            lastMode = mode;
+        }
+
+        if (!mSteps.isEmpty()) {
+            initTestStep(0);
+        }
+
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+
+        SurfaceView surfaceView = findViewById(R.id.surface);
+        mHolder = surfaceView.getHolder();
+        mHolder.addCallback(new SurfaceHolder.Callback() {
+            public void surfaceCreated(SurfaceHolder holder) {
+                playVideo();
+            }
+
+            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+            }
+
+            public void surfaceDestroyed(SurfaceHolder holder) {
+            }
+        });
+
+        AudioManager am = (AudioManager) getApplicationContext().getSystemService(AUDIO_SERVICE);
+        mAudioSessionId = am.generateAudioSessionId();
+
+        mPlayer = new MediaCodecTunneledPlayer(this, mHolder, true, mAudioSessionId);
+
+        Uri mediaUri = getAsResourceUri(R.raw.bunny_1280x720_24fps_VP9);
+        mPlayer.setVideoDataSource(mediaUri, null);
+        mPlayer.setAudioDataSource(mediaUri, null);
+    }
+
+    private Uri getAsResourceUri(int resId) {
+        Resources res = getResources();
+        return new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+                .authority(res.getResourcePackageName(resId))
+                .appendPath(res.getResourceTypeName(resId))
+                .appendPath(res.getResourceEntryName(resId))
+                .build();
+    }
+
+    private List<Display.Mode> findTestModes(Display display) {
+        Display.Mode activeMode = display.getMode();
+
+        List<Display.Mode> modeList = new ArrayList<>();
+        // Find a mode to test refresh rate switch - the mode with smallest refresh rate and
+        // the same resolution as the active mode
+        Arrays.stream(display.getSupportedModes())
+                .filter(mode -> !mode.equals(activeMode))
+                .filter(mode -> isResolutionEqual(mode, activeMode))
+                .min(Comparator.comparingDouble(Display.Mode::getRefreshRate))
+                .ifPresent(modeList::add);
+
+        // Find a mode to test seamless mode switch.
+        if (modeList.size() > 0 && !isSeamlessSwitch(activeMode, modeList.get(0))
+                && activeMode.getAlternativeRefreshRates().length > 0) {
+            Arrays.stream(display.getSupportedModes())
+                    .filter(mode -> !mode.equals(activeMode))
+                    .filter(mode -> isSeamlessSwitch(activeMode, mode))
+                    .findFirst()
+                    .ifPresent(modeList::add);
+        }
+
+        // Find a mode to test resolution switch - the first 16:9 mode with resolution less
+        // than the active mode.
+        Arrays.stream(display.getSupportedModes())
+                .filter(mode -> !mode.equals(activeMode))
+                .filter(mode -> !isResolutionEqual(mode, activeMode))
+                .filter(this::is16to9)
+                .max(Comparator.comparing(Display.Mode::getPhysicalHeight))
+                .ifPresent(modeList::add);
+
+        return modeList;
+    }
+
+    private void initTestStep(int stepIndex) {
+        final TestStepBase currStep = mSteps.get(stepIndex);
+        currStep.createUiElements()
+                .forEach(view -> mItemList.addView(view));
+
+        currStep.setOnDoneListener(() -> {
+            // Delay so the user can see the passing state of the finished
+            // step, before replacing it with the next one
+            mItemList.postDelayed(() -> {
+                int nextStepIndex = stepIndex + 1;
+                if (!currStep.hasPassed() || nextStepIndex >= mSteps.size()) {
+                    onAllStepsDone();
+                    return;
+                }
+
+                mItemList.removeAllViews();
+                initTestStep(nextStepIndex);
+            }, 500);
+        });
+
+        currStep.enableInteractivity();
+    }
+
+    private void onAllStepsDone() {
+        // The sequence passes if all containing test steps pass.
+        boolean allTestStepsPass = mSteps.stream().allMatch(step -> step.hasPassed());
+        getPassButton().setEnabled(allTestStepsPass);
+    }
+
+    private List<TestStepBase> createTestStepsForTransition(
+            Display.Mode currMode, Display.Mode nextMode, boolean isSeamless) {
+        List<TestStepBase> steps = new ArrayList<>();
+        steps.add(new ModeSwitchStep(this,
+                currMode,
+                nextMode
+                ));
+
+        String blackScreenQuestion =
+                getResources().getString(R.string.tv_mode_switching_test_black_screen_question);
+        if (isSeamless) {
+            steps.add(new YesNoTestStep(this, blackScreenQuestion,
+                    /* passingButton */ R.string.tv_no, /* failingButton */ R.string.tv_yes));
+        } else {
+            steps.add(new YesNoTestStep(this, blackScreenQuestion,
+                    /* passingButton */ R.string.tv_yes, /* failingButton */ R.string.tv_no));
+        }
+
+        steps.add(new YesNoTestStep(this,
+                getResources().getString(R.string.tv_mode_switching_test_is_video_ok),
+                R.string.tv_yes, R.string.tv_no));
+        return steps;
+
+    }
+
+    private boolean isSeamlessSwitch(Display.Mode from, Display.Mode to) {
+        if (!isResolutionEqual(from, to)) {
+            return false;
+        }
+
+        for (float refreshRate : from.getAlternativeRefreshRates()) {
+            if (Math.abs(refreshRate - to.getRefreshRate()) < REFRESH_RATE_TOLERANCE) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isResolutionEqual(Display.Mode left, Display.Mode right) {
+        return left.getPhysicalHeight() == right.getPhysicalHeight()
+                && left.getPhysicalWidth() == right.getPhysicalWidth();
+    }
+
+    private boolean is16to9(Display.Mode mode) {
+        return mode.getPhysicalHeight() * 16 == mode.getPhysicalWidth() * 9;
+    }
+
+
+    private void playVideo() {
+        try {
+            mPlayer.start();
+            mPlayer.prepare();
+            mPlayer.setLoopEnabled(true);
+            mPlayer.startThread();
+        } catch (Exception e) {
+            Log.d(TAG, "Could not play video", e);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (mPlayer != null) {
+            mPlayer.pause();
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (mPlayer != null) {
+            mPlayer.reset();
+            mPlayer = null;
+        }
+    }
+
+    @Override
+    public String getTestDetails() {
+        return mSteps.stream()
+                .filter(step -> !step.hasPassed())
+                .map(step -> step.getFailureDetails())
+                .collect(Collectors.joining("\n"));
+    }
+
+    // Test step which shows instruction text to the user and performs a mode switch. This
+    // test step will always pass successfully.
+    private static class ModeSwitchStep extends SyncTestStep {
+        private Display.Mode mNextMode;
+
+        ModeSwitchStep(Activity context, Display.Mode currMode, Display.Mode nextMode) {
+            super(context, R.string.tv_mode_switching_test_mode_switch_step,
+                    getInstructionText(context, currMode, nextMode),
+                    R.string.tv_start_test);
+            this.mNextMode = nextMode;
+        }
+
+        private static String getInstructionText(Context context, Display.Mode currMode,
+                Display.Mode nextMode) {
+            return context.getResources().getString(
+                    R.string.tv_mode_switching_test_step_instruction,
+                    formatMode(currMode),
+                    formatMode(nextMode));
+        }
+
+        private static String formatMode(Display.Mode mode) {
+            return String.format("%dx%d %.2fHz",
+                    mode.getPhysicalWidth(), mode.getPhysicalHeight(), mode.getRefreshRate());
+        }
+
+        @Override
+        public void runTest() {
+            Window window = mContext.getWindow();
+            WindowManager.LayoutParams params = window.getAttributes();
+            params.preferredDisplayModeId = mNextMode.getModeId();
+            window.setAttributes(params);
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/OneButtonTestStep.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/OneButtonTestStep.java
index 6ee34f3..89dc391 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/OneButtonTestStep.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/OneButtonTestStep.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.verifier.tv.display;
 
+import android.app.Activity;
 import android.view.View;
 
 import androidx.annotation.StringRes;
@@ -23,6 +24,8 @@
 import com.android.cts.verifier.tv.TestStepBase;
 import com.android.cts.verifier.tv.TvAppVerifierActivity;
 
+import java.util.List;
+
 /** Test step containing instruction to the user and a button. */
 public abstract class OneButtonTestStep extends TestStepBase {
 
@@ -42,7 +45,7 @@
      * @param buttonStringId Id of a string resource containing the text of the button.
      */
     public OneButtonTestStep(
-            TvAppVerifierActivity context,
+            Activity context,
             @StringRes int stepNameStringId,
             String instructionText,
             @StringRes int buttonStringId) {
@@ -52,21 +55,25 @@
     }
 
     @Override
-    public void createUiElements() {
-        super.createUiElements();
+    public List<View> createUiElements() {
+        List<View> list = super.createUiElements();
         mButtonView =
-                mContext.createButtonItem(
+                TvAppVerifierActivity.createButtonItem(mContext.getLayoutInflater(),
+                        null,
                         mButtonStringId,
                         (View view) -> {
                             String stepName = mContext.getString(mStepNameStringId);
                             appendInfoDetails("Running test step %s...", stepName);
                             onButtonClickRunTest();
                         });
+        list.add(mButtonView);
+        return list;
     }
 
     @Override
     public void enableInteractivity() {
         TvAppVerifierActivity.setButtonEnabled(mButtonView, true);
+        mButtonView.requestFocus();
     }
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/SyncTestStep.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/SyncTestStep.java
index a1736fb..f60db64 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/SyncTestStep.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/SyncTestStep.java
@@ -16,16 +16,16 @@
 
 package com.android.cts.verifier.tv.display;
 
-import androidx.annotation.StringRes;
+import android.app.Activity;
 
-import com.android.cts.verifier.tv.TvAppVerifierActivity;
+import androidx.annotation.StringRes;
 
 /**
  * Encapsulates the logic of a synchronously running test step, which displays human instructions
  * and a button to start the test. For asynchronous steps see {@link AsyncTestStep}.
  */
 public abstract class SyncTestStep extends OneButtonTestStep {
-    public SyncTestStep(TvAppVerifierActivity context, @StringRes int stepNameStringId,
+    public SyncTestStep(Activity context, @StringRes int stepNameStringId,
             String instructionText, @StringRes int buttonStringId) {
         super(context, stepNameStringId, instructionText, buttonStringId);
     }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/YesNoTestStep.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/YesNoTestStep.java
index 4f300d4..886c92c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/YesNoTestStep.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/YesNoTestStep.java
@@ -16,21 +16,24 @@
 
 package com.android.cts.verifier.tv.display;
 
+import android.app.Activity;
 import android.view.View;
 
-import com.android.cts.verifier.R;
 import com.android.cts.verifier.tv.TestStepBase;
 import com.android.cts.verifier.tv.TvAppVerifierActivity;
 
+import java.util.List;
+
 /**
  * Encapsulates the logic of a test step, which displays human instructions for a manual test and
  * two buttons - Yes and No, which respectively set the test in passing and failing state.
  */
-public abstract class YesNoTestStep extends TestStepBase {
-    private View positiveButton;
-    private View negativeButton;
-    private final int positiveButtonText;
-    private final int negativeButtonText;
+public class YesNoTestStep extends TestStepBase {
+    private View mPositiveButton;
+    private View mNegativeButton;
+    private final int mPositiveButtonText;
+    private final int mNegativeButtonText;
+
     /**
      * Constructs a test step containing human instructions for a manual test and two buttons - Yes
      * and No.
@@ -38,43 +41,54 @@
      * @param context The test activity which this test step is part of.
      * @param instructionText The text of the test instruction visible to the user.
      */
-    public YesNoTestStep(TvAppVerifierActivity context, String instructionText, 
+    public YesNoTestStep(Activity context, String instructionText,
             int positiveButtonText, int negativeButtonText) {
         super(context, instructionText);
-        this.positiveButtonText = positiveButtonText;
-        this.negativeButtonText = negativeButtonText;
+        this.mPositiveButtonText = positiveButtonText;
+        this.mNegativeButtonText = negativeButtonText;
     }
 
     @Override
-    public void createUiElements() {
-        super.createUiElements();
-        positiveButton =
-                mContext.createButtonItem(
-                        positiveButtonText,
+    public List<View> createUiElements() {
+        List<View> list = super.createUiElements();
+        mPositiveButton =
+                TvAppVerifierActivity.createButtonItem(
+                        mContext.getLayoutInflater(),
+                        null,
+                        mPositiveButtonText,
+
                         (View view) -> {
                             disableInteractivity();
                             // do nothing so the test will pass
                             done();
                         });
-        negativeButton =
-                mContext.createButtonItem(
-                        negativeButtonText,
+        list.add(mPositiveButton);
+
+        mNegativeButton =
+                TvAppVerifierActivity.createButtonItem(
+                        mContext.getLayoutInflater(),
+                        null,
+                        mNegativeButtonText,
                         (View view) -> {
                             disableInteractivity();
                             getAsserter().fail();
                             done();
                         });
+        list.add(mNegativeButton);
+
+        return list;
     }
 
     @Override
     public void enableInteractivity() {
-        TvAppVerifierActivity.setButtonEnabled(positiveButton, true);
-        TvAppVerifierActivity.setButtonEnabled(negativeButton, true);
+        TvAppVerifierActivity.setButtonEnabled(mPositiveButton, true);
+        TvAppVerifierActivity.setButtonEnabled(mNegativeButton, true);
+        mPositiveButton.requestFocus();
     }
 
     @Override
     public void disableInteractivity() {
-        TvAppVerifierActivity.setButtonEnabled(positiveButton, false);
-        TvAppVerifierActivity.setButtonEnabled(negativeButton, false);
+        TvAppVerifierActivity.setButtonEnabled(mPositiveButton, false);
+        TvAppVerifierActivity.setButtonEnabled(mNegativeButton, false);
     }
 }
diff --git a/common/device-side/bedstead/eventlib/Android.bp b/common/device-side/bedstead/eventlib/Android.bp
index 52545a6..cef979c 100644
--- a/common/device-side/bedstead/eventlib/Android.bp
+++ b/common/device-side/bedstead/eventlib/Android.bp
@@ -11,7 +11,8 @@
     ],
     static_libs: [
         "Nene",
-        "androidx.test.ext.junit"],
+        "Queryable"
+    ],
     manifest: "src/main/AndroidManifest.xml",
     min_sdk_version: "27"
 }
diff --git a/common/device-side/bedstead/eventlib/OWNERS b/common/device-side/bedstead/eventlib/OWNERS
deleted file mode 100644
index ce3438f..0000000
--- a/common/device-side/bedstead/eventlib/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-scottjonathan@google.com
-alexkershaw@google.com
\ No newline at end of file
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/EventLogsQuery.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/EventLogsQuery.java
index 35bdf2a..379d297 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/EventLogsQuery.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/EventLogsQuery.java
@@ -19,6 +19,7 @@
 import android.os.UserHandle;
 
 import com.android.bedstead.nene.users.UserReference;
+import com.android.queryable.Queryable;
 
 import java.util.HashSet;
 import java.util.Set;
@@ -28,7 +29,7 @@
  * Interface to provide additional restrictions on an {@link Event} query.
  */
 public abstract class EventLogsQuery<E extends Event, F extends EventLogsQuery>
-        extends EventLogs<E> {
+        extends EventLogs<E> implements Queryable {
 
     /**
      * Default implementation of {@link EventLogsQuery} used when there are no additional query
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/CustomEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/CustomEvent.java
index 26c0906..ea05843 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/CustomEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/CustomEvent.java
@@ -23,10 +23,10 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.queryhelpers.SerializableQuery;
-import com.android.eventlib.queryhelpers.SerializableQueryHelper;
-import com.android.eventlib.queryhelpers.StringQuery;
-import com.android.eventlib.queryhelpers.StringQueryHelper;
+import com.android.queryable.queries.SerializableQuery;
+import com.android.queryable.queries.SerializableQueryHelper;
+import com.android.queryable.queries.StringQuery;
+import com.android.queryable.queries.StringQueryHelper;
 
 import java.io.Serializable;
 
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityCreatedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityCreatedEvent.java
index 0e9660c..2474368 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityCreatedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityCreatedEvent.java
@@ -25,13 +25,13 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.ActivityInfo;
-import com.android.eventlib.queryhelpers.ActivityQuery;
-import com.android.eventlib.queryhelpers.ActivityQueryHelper;
-import com.android.eventlib.queryhelpers.BundleQueryHelper;
-import com.android.eventlib.queryhelpers.PersistableBundleQuery;
-import com.android.eventlib.queryhelpers.PersistableBundleQueryHelper;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.info.ActivityInfo;
+import com.android.queryable.queries.ActivityQuery;
+import com.android.queryable.queries.ActivityQueryHelper;
+import com.android.queryable.queries.BundleQueryHelper;
+import com.android.queryable.queries.PersistableBundleQuery;
+import com.android.queryable.queries.PersistableBundleQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
 
 /**
  * Event logged when {@link Activity#onCreate(Bundle)} or
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityDestroyedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityDestroyedEvent.java
index da40ebf..88a00de 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityDestroyedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityDestroyedEvent.java
@@ -23,9 +23,9 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.ActivityInfo;
-import com.android.eventlib.queryhelpers.ActivityQuery;
-import com.android.eventlib.queryhelpers.ActivityQueryHelper;
+import com.android.queryable.info.ActivityInfo;
+import com.android.queryable.queries.ActivityQuery;
+import com.android.queryable.queries.ActivityQueryHelper;
 
 /**
  * Event logged when {@link Activity#onDestroy()} is called.
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityPausedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityPausedEvent.java
index 5f22317..2e706ef 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityPausedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityPausedEvent.java
@@ -23,9 +23,9 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.ActivityInfo;
-import com.android.eventlib.queryhelpers.ActivityQuery;
-import com.android.eventlib.queryhelpers.ActivityQueryHelper;
+import com.android.queryable.info.ActivityInfo;
+import com.android.queryable.queries.ActivityQuery;
+import com.android.queryable.queries.ActivityQueryHelper;
 
 /**
  * Event logged when {@link Activity#onPause()} is called.
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityRestartedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityRestartedEvent.java
index c8f6d86..40a9eb9 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityRestartedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityRestartedEvent.java
@@ -23,9 +23,9 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.ActivityInfo;
-import com.android.eventlib.queryhelpers.ActivityQuery;
-import com.android.eventlib.queryhelpers.ActivityQueryHelper;
+import com.android.queryable.info.ActivityInfo;
+import com.android.queryable.queries.ActivityQuery;
+import com.android.queryable.queries.ActivityQueryHelper;
 
 /**
  * Event logged when {@link Activity#onRestart()} is called.
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityResumedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityResumedEvent.java
index 5d10f83..72c3b3b 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityResumedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityResumedEvent.java
@@ -23,9 +23,9 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.ActivityInfo;
-import com.android.eventlib.queryhelpers.ActivityQuery;
-import com.android.eventlib.queryhelpers.ActivityQueryHelper;
+import com.android.queryable.info.ActivityInfo;
+import com.android.queryable.queries.ActivityQuery;
+import com.android.queryable.queries.ActivityQueryHelper;
 
 /**
  * Event logged when {@link Activity#onResume()}} is called.
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStartedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStartedEvent.java
index e0ee657..e320980 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStartedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStartedEvent.java
@@ -23,9 +23,9 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.ActivityInfo;
-import com.android.eventlib.queryhelpers.ActivityQuery;
-import com.android.eventlib.queryhelpers.ActivityQueryHelper;
+import com.android.queryable.info.ActivityInfo;
+import com.android.queryable.queries.ActivityQuery;
+import com.android.queryable.queries.ActivityQueryHelper;
 
 /**
  * Event logged when {@link Activity#onStart()} is called.
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStoppedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStoppedEvent.java
index 736a097..fd802c7 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStoppedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/activities/ActivityStoppedEvent.java
@@ -23,9 +23,9 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.ActivityInfo;
-import com.android.eventlib.queryhelpers.ActivityQuery;
-import com.android.eventlib.queryhelpers.ActivityQueryHelper;
+import com.android.queryable.info.ActivityInfo;
+import com.android.queryable.queries.ActivityQuery;
+import com.android.queryable.queries.ActivityQueryHelper;
 
 /**
  * Event logged when {@link Activity#onStop()} is called.
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/broadcastreceivers/BroadcastReceivedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/broadcastreceivers/BroadcastReceivedEvent.java
index b4a2717..ff849a0 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/broadcastreceivers/BroadcastReceivedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/broadcastreceivers/BroadcastReceivedEvent.java
@@ -25,12 +25,12 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.BroadcastReceiverInfo;
-import com.android.eventlib.queryhelpers.BroadcastReceiverQuery;
-import com.android.eventlib.queryhelpers.BroadcastReceiverQueryHelper;
-import com.android.eventlib.queryhelpers.IntentQuery;
-import com.android.eventlib.queryhelpers.IntentQueryHelper;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.info.BroadcastReceiverInfo;
+import com.android.queryable.queries.BroadcastReceiverQuery;
+import com.android.queryable.queries.BroadcastReceiverQueryHelper;
+import com.android.queryable.queries.IntentQuery;
+import com.android.queryable.queries.IntentQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
 
 /**
  * Event logged when {@link BroadcastReceiver#onReceive(Context, Intent)} is called.
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisableRequestedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisableRequestedEvent.java
index f1f82df..397399b 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisableRequestedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisableRequestedEvent.java
@@ -25,11 +25,11 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.DeviceAdminReceiverInfo;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQuery;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQueryHelper;
-import com.android.eventlib.queryhelpers.IntentQueryHelper;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.info.DeviceAdminReceiverInfo;
+import com.android.queryable.queries.DeviceAdminReceiverQuery;
+import com.android.queryable.queries.DeviceAdminReceiverQueryHelper;
+import com.android.queryable.queries.IntentQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
 
 /**
  * Event logged when {@link DeviceAdminReceiver#onDisableRequested(Context, Intent)} is called.
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisabledEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisabledEvent.java
index 25bd3d9..d3ccc35 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisabledEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminDisabledEvent.java
@@ -25,11 +25,11 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.DeviceAdminReceiverInfo;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQuery;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQueryHelper;
-import com.android.eventlib.queryhelpers.IntentQueryHelper;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.info.DeviceAdminReceiverInfo;
+import com.android.queryable.queries.DeviceAdminReceiverQuery;
+import com.android.queryable.queries.DeviceAdminReceiverQueryHelper;
+import com.android.queryable.queries.IntentQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
 
 /**
  * Event logged when {@link DeviceAdminReceiver#onDisabled(Context, Intent)} is called.
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminEnabledEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminEnabledEvent.java
index b390ed8..1ea2699 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminEnabledEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminEnabledEvent.java
@@ -25,11 +25,11 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.DeviceAdminReceiverInfo;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQuery;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQueryHelper;
-import com.android.eventlib.queryhelpers.IntentQueryHelper;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.info.DeviceAdminReceiverInfo;
+import com.android.queryable.queries.DeviceAdminReceiverQuery;
+import com.android.queryable.queries.DeviceAdminReceiverQueryHelper;
+import com.android.queryable.queries.IntentQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
 
 /**
  * Event logged when {@link DeviceAdminReceiver#onEnabled(Context, Intent)} is called.
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordChangedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordChangedEvent.java
index 82998d6..5e09058 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordChangedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordChangedEvent.java
@@ -26,13 +26,13 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.DeviceAdminReceiverInfo;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQuery;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQueryHelper;
-import com.android.eventlib.queryhelpers.IntentQueryHelper;
-import com.android.eventlib.queryhelpers.UserHandleQuery;
-import com.android.eventlib.queryhelpers.UserHandleQueryHelper;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.info.DeviceAdminReceiverInfo;
+import com.android.queryable.queries.DeviceAdminReceiverQuery;
+import com.android.queryable.queries.DeviceAdminReceiverQueryHelper;
+import com.android.queryable.queries.IntentQueryHelper;
+import com.android.queryable.queries.UserHandleQuery;
+import com.android.queryable.queries.UserHandleQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
 
 /**
  * Event logged when {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent)} or
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordFailedEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordFailedEvent.java
index b796a25..9bc1c84 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordFailedEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordFailedEvent.java
@@ -26,13 +26,13 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.DeviceAdminReceiverInfo;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQuery;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQueryHelper;
-import com.android.eventlib.queryhelpers.IntentQueryHelper;
-import com.android.eventlib.queryhelpers.UserHandleQuery;
-import com.android.eventlib.queryhelpers.UserHandleQueryHelper;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.info.DeviceAdminReceiverInfo;
+import com.android.queryable.queries.DeviceAdminReceiverQuery;
+import com.android.queryable.queries.DeviceAdminReceiverQueryHelper;
+import com.android.queryable.queries.IntentQueryHelper;
+import com.android.queryable.queries.UserHandleQuery;
+import com.android.queryable.queries.UserHandleQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
 
 /**
  * Event logged when {@link DeviceAdminReceiver#onPasswordFailed(Context, Intent)} or
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordSucceededEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordSucceededEvent.java
index ba22d98..f6a0504 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordSucceededEvent.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/deviceadminreceivers/DeviceAdminPasswordSucceededEvent.java
@@ -26,13 +26,13 @@
 import com.android.eventlib.Event;
 import com.android.eventlib.EventLogger;
 import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.DeviceAdminReceiverInfo;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQuery;
-import com.android.eventlib.queryhelpers.DeviceAdminReceiverQueryHelper;
-import com.android.eventlib.queryhelpers.IntentQueryHelper;
-import com.android.eventlib.queryhelpers.UserHandleQuery;
-import com.android.eventlib.queryhelpers.UserHandleQueryHelper;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.info.DeviceAdminReceiverInfo;
+import com.android.queryable.queries.DeviceAdminReceiverQuery;
+import com.android.queryable.queries.DeviceAdminReceiverQueryHelper;
+import com.android.queryable.queries.IntentQueryHelper;
+import com.android.queryable.queries.UserHandleQuery;
+import com.android.queryable.queries.UserHandleQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
 
 /**
  * Event logged when {@link DeviceAdminReceiver#onPasswordSucceeded(Context, Intent)} or
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/PreferentialNetworkService.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/PreferentialNetworkService.java
new file mode 100644
index 0000000..5676b87
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/PreferentialNetworkService.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.policies;
+
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.DeviceOwnerControl.NO;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.ProfileOwnerControl.PROFILE;
+
+import android.app.admin.DevicePolicyManager;
+
+import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
+
+/**
+ * Policy for testing preferential network service.
+ * See {@link DevicePolicyManager#setPreferentialNetworkServiceEnabled(boolean)} for more detail.
+ */
+@EnterprisePolicy(deviceOwner = NO, profileOwner = PROFILE)
+public final class PreferentialNetworkService {
+}
diff --git a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DeviceOwnerTest.java b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DeviceOwnerTest.java
index de0cb4d..da5c693 100644
--- a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DeviceOwnerTest.java
+++ b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DeviceOwnerTest.java
@@ -50,7 +50,7 @@
     @BeforeClass
     public static void setupClass() {
         sTestApp = new TestAppProvider().query()
-                .withPackageName(DEVICE_ADMIN_TESTAPP_PACKAGE_NAME)
+                .wherePackageName().isEqualTo(DEVICE_ADMIN_TESTAPP_PACKAGE_NAME)
                 .get();
 
         sTestApp.install(sUser);
diff --git a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DevicePolicyTest.java b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DevicePolicyTest.java
index 5889233..d3923cd 100644
--- a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DevicePolicyTest.java
+++ b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/DevicePolicyTest.java
@@ -74,7 +74,7 @@
     @BeforeClass
     public static void setupClass() {
         sTestApp = new TestAppProvider().query()
-                .withPackageName(DEVICE_ADMIN_TESTAPP_PACKAGE_NAME)
+                .wherePackageName().isEqualTo(DEVICE_ADMIN_TESTAPP_PACKAGE_NAME)
                 .get();
 
         sTestApp.install(sUser);
diff --git a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/ProfileOwnerTest.java b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/ProfileOwnerTest.java
index 5bc0232..f388354 100644
--- a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/ProfileOwnerTest.java
+++ b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/devicepolicy/ProfileOwnerTest.java
@@ -57,7 +57,7 @@
                 .createAndStart();
 
         sTestApp = new TestAppProvider().query()
-                .withPackageName(DEVICE_ADMIN_TESTAPP_PACKAGE_NAME)
+                .wherePackageName().isEqualTo(DEVICE_ADMIN_TESTAPP_PACKAGE_NAME)
                 .get();
 
         sTestApp.install(sProfile);
diff --git a/common/device-side/bedstead/queryable/Android.bp b/common/device-side/bedstead/queryable/Android.bp
new file mode 100644
index 0000000..edae7901
--- /dev/null
+++ b/common/device-side/bedstead/queryable/Android.bp
@@ -0,0 +1,34 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_library {
+    name: "Queryable",
+    sdk_version: "test_current",
+    srcs: [
+        "src/main/java/**/*.java",
+    ],
+    static_libs: ["androidx.test.ext.junit"],
+    manifest: "src/main/AndroidManifest.xml",
+    min_sdk_version: "27"
+}
+
+android_test {
+    name: "BedsteadQueryableTest",
+    srcs: [
+        "src/test/java/**/*.java"
+    ],
+    test_suites: [
+        "general-tests",
+    ],
+    static_libs: [
+        "Queryable",
+        "ActivityContext",
+        "androidx.test.ext.junit",
+        "ctstestrunner-axt",
+        "truth-prebuilt",
+        "testng", // for assertThrows
+    ],
+    manifest: "src/test/AndroidManifest.xml",
+    min_sdk_version: "27"
+}
diff --git a/common/device-side/bedstead/queryable/AndroidTest.xml b/common/device-side/bedstead/queryable/AndroidTest.xml
new file mode 100644
index 0000000..32d559d
--- /dev/null
+++ b/common/device-side/bedstead/queryable/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<configuration description="Config for Event Library test cases">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="BedsteadQueryableTest.apk" />
+        <option name="install-arg" value="-t" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.queryable.test" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/common/device-side/bedstead/queryable/TEST_MAPPING b/common/device-side/bedstead/queryable/TEST_MAPPING
new file mode 100644
index 0000000..62bc822
--- /dev/null
+++ b/common/device-side/bedstead/queryable/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "postsubmit": [
+    {
+      "name": "BedsteadQueryableTest"
+    }
+  ]
+}
diff --git a/common/device-side/bedstead/queryable/src/main/AndroidManifest.xml b/common/device-side/bedstead/queryable/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..836303a
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.queryable">
+    <uses-sdk android:minSdkVersion="27" />
+    <application>
+    </application>
+</manifest>
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ActivityQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/Queryable.java
similarity index 71%
copy from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ActivityQuery.java
copy to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/Queryable.java
index 91d67ea..09bd40a 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ActivityQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/Queryable.java
@@ -14,13 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable;
 
-import android.app.Activity;
-
-import com.android.eventlib.EventLogsQuery;
-
-/** Query for an {@link Activity}. */
-public interface ActivityQuery<E extends EventLogsQuery> extends ClassQuery<E>  {
-
+public interface Queryable {
 }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/ActivityInfo.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/ActivityInfo.java
similarity index 97%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/ActivityInfo.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/ActivityInfo.java
index 41ccb8a..632afab 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/ActivityInfo.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/ActivityInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.info;
+package com.android.queryable.info;
 
 import android.app.Activity;
 
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/BroadcastReceiverInfo.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/BroadcastReceiverInfo.java
similarity index 97%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/BroadcastReceiverInfo.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/BroadcastReceiverInfo.java
index 83095be..30c19e9 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/BroadcastReceiverInfo.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/BroadcastReceiverInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.info;
+package com.android.queryable.info;
 
 import android.content.BroadcastReceiver;
 
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/ClassInfo.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/ClassInfo.java
similarity index 97%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/ClassInfo.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/ClassInfo.java
index b0d245a..a964335 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/ClassInfo.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/ClassInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.info;
+package com.android.queryable.info;
 
 import java.io.Serializable;
 
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/DeviceAdminReceiverInfo.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/DeviceAdminReceiverInfo.java
similarity index 97%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/DeviceAdminReceiverInfo.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/DeviceAdminReceiverInfo.java
index 611e216..4660203 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/info/DeviceAdminReceiverInfo.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/DeviceAdminReceiverInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.info;
+package com.android.queryable.info;
 
 import android.app.admin.DeviceAdminReceiver;
 
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ActivityQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQuery.java
similarity index 80%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ActivityQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQuery.java
index 91d67ea..8fe37eb 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ActivityQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQuery.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.app.Activity;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 /** Query for an {@link Activity}. */
-public interface ActivityQuery<E extends EventLogsQuery> extends ClassQuery<E>  {
+public interface ActivityQuery<E extends Queryable> extends ClassQuery<E>  {
 
 }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ActivityQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQueryHelper.java
similarity index 85%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ActivityQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQueryHelper.java
index 8389d4c..77a6191 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ActivityQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ActivityQueryHelper.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
-import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.ActivityInfo;
+import com.android.queryable.Queryable;
+import com.android.queryable.info.ActivityInfo;
 
 /** Implementation of {@link ActivityQuery}. */
-public final class ActivityQueryHelper<E extends EventLogsQuery> implements ActivityQuery<E> {
+public final class ActivityQueryHelper<E extends Queryable> implements ActivityQuery<E> {
 
     private final E mQuery;
     private final ClassQueryHelper<E> mClassQueryHelper;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BroadcastReceiverQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQuery.java
similarity index 79%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BroadcastReceiverQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQuery.java
index be8f659..45febeb 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BroadcastReceiverQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQuery.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.content.BroadcastReceiver;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 /** Query for an {@link BroadcastReceiver}. */
-public interface BroadcastReceiverQuery<E extends EventLogsQuery> extends ClassQuery<E>  {
+public interface BroadcastReceiverQuery<E extends Queryable> extends ClassQuery<E>  {
 
 }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BroadcastReceiverQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQueryHelper.java
similarity index 86%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BroadcastReceiverQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQueryHelper.java
index 4957cd4..a63f700 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BroadcastReceiverQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BroadcastReceiverQueryHelper.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
-import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.BroadcastReceiverInfo;
+import com.android.queryable.Queryable;
+import com.android.queryable.info.BroadcastReceiverInfo;
 
 /** Implementation of {@link BroadcastReceiverQuery}. */
-public final class BroadcastReceiverQueryHelper<E extends EventLogsQuery>
+public final class BroadcastReceiverQueryHelper<E extends Queryable>
         implements BroadcastReceiverQuery<E> {
 
     private final E mQuery;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleKeyQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleKeyQuery.java
similarity index 86%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleKeyQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleKeyQuery.java
index 035285c..0ec1156 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleKeyQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleKeyQuery.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.os.Bundle;
 
 import androidx.annotation.CheckResult;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Query for a single key in a {@link Bundle}. */
-public interface BundleKeyQuery<E extends EventLogsQuery> extends Serializable {
+public interface BundleKeyQuery<E extends Queryable> extends Serializable {
 
     /** Require that the key exists. */
     E exists();
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleKeyQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleKeyQueryHelper.java
similarity index 94%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleKeyQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleKeyQueryHelper.java
index f5851a4..f102e7d 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleKeyQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleKeyQueryHelper.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.os.Bundle;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Implementation of {@link BundleKeyQuery}. */
-public final class BundleKeyQueryHelper<E extends EventLogsQuery> implements BundleKeyQuery<E>,
+public final class BundleKeyQueryHelper<E extends Queryable> implements BundleKeyQuery<E>,
         Serializable {
 
     private final E mQuery;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQuery.java
similarity index 83%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQuery.java
index cf9fd77..123f9e8 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQuery.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.os.Bundle;
 
 import androidx.annotation.CheckResult;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Query for a {@link Bundle}. */
-public interface BundleQuery<E extends EventLogsQuery>  extends Serializable {
+public interface BundleQuery<E extends Queryable>  extends Serializable {
 
     /** Query a given key on the {@link Bundle}. */
     @CheckResult
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQueryHelper.java
similarity index 88%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQueryHelper.java
index dc60387..ae4b85e 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/BundleQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/BundleQueryHelper.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.os.Bundle;
 
-import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.util.SerializableParcelWrapper;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 import java.util.HashMap;
 import java.util.Map;
 
 /** Implementation of {@link BundleQuery}. */
-public final class BundleQueryHelper<E extends EventLogsQuery> implements BundleQuery<E>,
+public final class BundleQueryHelper<E extends Queryable> implements BundleQuery<E>,
         Serializable {
 
     private final E mQuery;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ClassQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQuery.java
similarity index 84%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ClassQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQuery.java
index 997ff68..8fd7b1d 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ClassQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQuery.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import androidx.annotation.CheckResult;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Query for a {@link Class}. */
-public interface ClassQuery<E extends EventLogsQuery> extends Serializable {
+public interface ClassQuery<E extends Queryable> extends Serializable {
     /** Require that the class is the same as {@code clazz}. */
     E isSameClassAs(Class<?> clazz);
 
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ClassQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQueryHelper.java
similarity index 89%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ClassQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQueryHelper.java
index 0c17d18..3eca12d 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/ClassQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/ClassQueryHelper.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
-import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.ClassInfo;
+import com.android.queryable.Queryable;
+import com.android.queryable.info.ClassInfo;
 
 import java.io.Serializable;
 
 /** Implementation of {@link ClassQuery}. */
-public final class ClassQueryHelper<E extends EventLogsQuery>
+public final class ClassQueryHelper<E extends Queryable>
         implements ClassQuery<E>, Serializable {
 
     private final E mQuery;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/DeviceAdminReceiverQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQuery.java
similarity index 82%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/DeviceAdminReceiverQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQuery.java
index 3baea1e..40a2ffe 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/DeviceAdminReceiverQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQuery.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.app.admin.DeviceAdminReceiver;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 /** Query for a {@link DeviceAdminReceiver}. */
-public interface DeviceAdminReceiverQuery<E extends EventLogsQuery>
+public interface DeviceAdminReceiverQuery<E extends Queryable>
         extends BroadcastReceiverQuery<E>  {
 
 }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/DeviceAdminReceiverQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQueryHelper.java
similarity index 86%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/DeviceAdminReceiverQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQueryHelper.java
index 6ed0750..68cec2f 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/DeviceAdminReceiverQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DeviceAdminReceiverQueryHelper.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
-import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.info.DeviceAdminReceiverInfo;
+import com.android.queryable.Queryable;
+import com.android.queryable.info.DeviceAdminReceiverInfo;
 
 /** Implementation of {@link DeviceAdminReceiverQuery}. */
-public final class DeviceAdminReceiverQueryHelper<E extends EventLogsQuery>
+public final class DeviceAdminReceiverQueryHelper<E extends Queryable>
         implements DeviceAdminReceiverQuery<E> {
 
     private final E mQuery;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntegerQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQuery.java
similarity index 87%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntegerQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQuery.java
index 92b2469..5cb442f 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntegerQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQuery.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Query for a {@link Integer}. */
-public interface IntegerQuery<E extends EventLogsQuery> extends Serializable {
+public interface IntegerQuery<E extends Queryable> extends Serializable {
     /** Require the {@link Integer} is equal to {@code i}. */
     E isEqualTo(int i);
 
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntegerQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQueryHelper.java
similarity index 93%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntegerQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQueryHelper.java
index 1661954..c6519d4 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntegerQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntegerQueryHelper.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Implementation of {@link IntegerQuery}. */
-public final class IntegerQueryHelper<E extends EventLogsQuery> implements IntegerQuery<E>,
+public final class IntegerQueryHelper<E extends Queryable> implements IntegerQuery<E>,
         Serializable {
 
     private Integer mEqualToValue = null;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntentQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQuery.java
similarity index 83%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntentQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQuery.java
index 45d1e9a..3c83f24 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntentQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQuery.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.content.Intent;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Query for a {@link Intent}. */
-public interface IntentQuery<E extends EventLogsQuery>  extends Serializable {
+public interface IntentQuery<E extends Queryable>  extends Serializable {
 
     /** Query the {@link Intent#getAction}. */
     StringQuery<E> action();
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntentQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQueryHelper.java
similarity index 88%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntentQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQueryHelper.java
index 459c29e..d7774e7 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/IntentQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/IntentQueryHelper.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.content.Intent;
 
-import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.util.SerializableParcelWrapper;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Implementation of {@link IntentQuery}. */
-public final class IntentQueryHelper<E extends EventLogsQuery> implements IntentQuery<E>,
+public final class IntentQueryHelper<E extends Queryable> implements IntentQuery<E>,
         Serializable {
 
     private final E mQuery;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleKeyQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleKeyQuery.java
similarity index 85%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleKeyQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleKeyQuery.java
index dd3112a..9e75564 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleKeyQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleKeyQuery.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.os.PersistableBundle;
 
 import androidx.annotation.CheckResult;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Query for a single key in a {@link PersistableBundle}. */
-public interface PersistableBundleKeyQuery<E extends EventLogsQuery>  extends Serializable {
+public interface PersistableBundleKeyQuery<E extends Queryable>  extends Serializable {
     /** Require that the key exists. */
     E exists();
     /** Require that the key does not exist. */
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleKeyQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleKeyQueryHelper.java
similarity index 94%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleKeyQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleKeyQueryHelper.java
index aca4e94..ddc9370 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleKeyQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleKeyQueryHelper.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.os.PersistableBundle;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Implementation of {@link PersistableBundleKeyQuery}. */
-public final class PersistableBundleKeyQueryHelper<E extends EventLogsQuery>
+public final class PersistableBundleKeyQueryHelper<E extends Queryable>
         implements PersistableBundleKeyQuery<E>, Serializable {
 
     private final E mQuery;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQuery.java
similarity index 83%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQuery.java
index 4df56a2..67930a7d 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQuery.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.os.PersistableBundle;
 
 import androidx.annotation.CheckResult;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Query for a {@link PersistableBundle}. */
-public interface PersistableBundleQuery<E extends EventLogsQuery> extends Serializable {
+public interface PersistableBundleQuery<E extends Queryable> extends Serializable {
 
     /** Query a given key on the {@link PersistableBundle}. */
     @CheckResult
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQueryHelper.java
similarity index 89%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQueryHelper.java
index 407e2ca..287f05a 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/PersistableBundleQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/PersistableBundleQueryHelper.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.os.PersistableBundle;
 
-import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.util.SerializableParcelWrapper;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 import java.util.HashMap;
 import java.util.Map;
 
 /** Implementation of {@link PersistableBundleQuery}. */
-public final class PersistableBundleQueryHelper<E extends EventLogsQuery>
+public final class PersistableBundleQueryHelper<E extends Queryable>
         implements PersistableBundleQuery<E>, Serializable {
 
     private final E mQuery;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/SerializableQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQuery.java
similarity index 82%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/SerializableQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQuery.java
index c57bc11..a511e42 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/SerializableQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQuery.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Query for a {@link Serializable}. */
-public interface SerializableQuery<E extends EventLogsQuery> extends Serializable {
+public interface SerializableQuery<E extends Queryable> extends Serializable {
     /** Require that the {@link Serializable} is equal to {@code serializable}. */
     E isEqualTo(Serializable serializable);
 }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/SerializableQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQueryHelper.java
similarity index 88%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/SerializableQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQueryHelper.java
index 9d24c49..655c55b 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/SerializableQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/SerializableQueryHelper.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Implementation of {@link SerializableQuery}. */
-public final class SerializableQueryHelper<E extends EventLogsQuery>
+public final class SerializableQueryHelper<E extends Queryable>
         implements SerializableQuery<E>, Serializable {
 
     private final E mQuery;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/StringQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQuery.java
similarity index 82%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/StringQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQuery.java
index 3721c7c..0dfb4b5 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/StringQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQuery.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Query for a {@link String}. */
-public interface StringQuery<E extends EventLogsQuery> extends Serializable {
+public interface StringQuery<E extends Queryable> extends Serializable {
     /** Require the {@link String} is equal to {@code string}. */
     E isEqualTo(String string);
 }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/StringQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQueryHelper.java
similarity index 88%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/StringQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQueryHelper.java
index b84ff1a..45b731c 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/StringQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/StringQueryHelper.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Implementation of {@link StringQuery}. */
-public final class StringQueryHelper<E extends EventLogsQuery>
+public final class StringQueryHelper<E extends Queryable>
         implements StringQuery<E>, Serializable{
 
     private final E mQuery;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/UserHandleQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQuery.java
similarity index 84%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/UserHandleQuery.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQuery.java
index c0d5d28..7d7fb32 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/UserHandleQuery.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQuery.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.os.UserHandle;
 
 import androidx.annotation.CheckResult;
 
-import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Query for a {@link UserHandle}. */
-public interface UserHandleQuery<E extends EventLogsQuery> extends Serializable {
+public interface UserHandleQuery<E extends Queryable> extends Serializable {
     /** Require the {@link UserHandle} is equal to {@code userHandle}. */
     E isEqualTo(UserHandle userHandle);
 
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/UserHandleQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQueryHelper.java
similarity index 90%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/UserHandleQueryHelper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQueryHelper.java
index 3b5254c..a4b0a09 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/queryhelpers/UserHandleQueryHelper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/UserHandleQueryHelper.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import android.os.UserHandle;
 
-import com.android.eventlib.EventLogsQuery;
-import com.android.eventlib.util.SerializableParcelWrapper;
+import com.android.queryable.util.SerializableParcelWrapper;
+import com.android.queryable.Queryable;
 
 import java.io.Serializable;
 
 /** Implementation of {@link UserHandleQuery}. */
-public final class UserHandleQueryHelper<E extends EventLogsQuery>
+public final class UserHandleQueryHelper<E extends Queryable>
         implements UserHandleQuery<E>, Serializable {
 
     private final E mQuery;
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/util/SerializableParcelWrapper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/util/SerializableParcelWrapper.java
similarity index 98%
rename from common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/util/SerializableParcelWrapper.java
rename to common/device-side/bedstead/queryable/src/main/java/com/android/queryable/util/SerializableParcelWrapper.java
index e0fa4b2..0d08c37 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/util/SerializableParcelWrapper.java
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/util/SerializableParcelWrapper.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.util;
+package com.android.queryable.util;
 
 import android.os.Parcel;
 import android.os.Parcelable;
diff --git a/common/device-side/bedstead/queryable/src/test/AndroidManifest.xml b/common/device-side/bedstead/queryable/src/test/AndroidManifest.xml
new file mode 100644
index 0000000..986faae
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/test/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.queryable.test">
+    <uses-sdk android:minSdkVersion="27" android:targetSdkVersion="27"/>
+    <application
+        android:label="Queryable Tests"
+        android:testOnly="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.queryable.test"
+                     android:label="Queryable Tests" />
+</manifest>
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/ActivityInfoTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/ActivityInfoTest.java
similarity index 95%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/ActivityInfoTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/ActivityInfoTest.java
index 17b8e1d..dc3142e 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/ActivityInfoTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/ActivityInfoTest.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.info;
+package com.android.queryable.info;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.app.Activity;
 
 import com.android.activitycontext.ActivityContext;
+import com.android.queryable.info.ActivityInfo;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/BroadcastReceiverInfoTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/BroadcastReceiverInfoTest.java
similarity index 96%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/BroadcastReceiverInfoTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/BroadcastReceiverInfoTest.java
index 2121c86..d8b906d 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/BroadcastReceiverInfoTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/BroadcastReceiverInfoTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.info;
+package com.android.queryable.info;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -22,6 +22,8 @@
 import android.content.Context;
 import android.content.Intent;
 
+import com.android.queryable.info.BroadcastReceiverInfo;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/ClassInfoTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/ClassInfoTest.java
similarity index 97%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/ClassInfoTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/ClassInfoTest.java
index 615cda1..db4cf81 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/ClassInfoTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/ClassInfoTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.info;
+package com.android.queryable.info;
 
 import static com.google.common.truth.Truth.assertThat;
 
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/DeviceAdminReceiverInfoTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/DeviceAdminReceiverInfoTest.java
similarity index 96%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/DeviceAdminReceiverInfoTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/DeviceAdminReceiverInfoTest.java
index 52505ed..6e0214b 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/info/DeviceAdminReceiverInfoTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/DeviceAdminReceiverInfoTest.java
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.info;
+package com.android.queryable.info;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.app.admin.DeviceAdminReceiver;
 
+import com.android.queryable.info.DeviceAdminReceiverInfo;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/ActivityQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ActivityQueryHelperTest.java
similarity index 79%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/ActivityQueryHelperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ActivityQueryHelperTest.java
index ce14238..25c77d5 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/ActivityQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ActivityQueryHelperTest.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.app.Activity;
 
-import com.android.eventlib.events.CustomEvent;
-import com.android.eventlib.info.ActivityInfo;
+import com.android.queryable.Queryable;
+import com.android.queryable.info.ActivityInfo;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -30,8 +30,7 @@
 @RunWith(JUnit4.class)
 public class ActivityQueryHelperTest {
 
-    private final CustomEvent.CustomEventQuery mQuery =
-            CustomEvent.queryPackage("testPackage"); // package is not used
+    private final Queryable mQuery = null;
 
     private static final Class<? extends Activity> CLASS_1 = Activity.class;
     private static final ActivityInfo CLASS_1_ACTIVITY_INFO = new ActivityInfo(CLASS_1);
@@ -42,7 +41,7 @@
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
-        ActivityQueryHelper<CustomEvent.CustomEventQuery> activityQueryHelper =
+        ActivityQueryHelper<Queryable> activityQueryHelper =
                 new ActivityQueryHelper<>(mQuery);
 
         assertThat(activityQueryHelper.matches(CLASS_1_ACTIVITY_INFO)).isTrue();
@@ -50,7 +49,7 @@
 
     @Test
     public void matches_isSameClassAs_doesMatch_returnsTrue() {
-        ActivityQueryHelper<CustomEvent.CustomEventQuery> activityQueryHelper =
+        ActivityQueryHelper<Queryable> activityQueryHelper =
                 new ActivityQueryHelper<>(mQuery);
 
         activityQueryHelper.isSameClassAs(CLASS_1);
@@ -60,7 +59,7 @@
 
     @Test
     public void matches_isSameClassAs_doesNotMatch_returnsFalse() {
-        ActivityQueryHelper<CustomEvent.CustomEventQuery> activityQueryHelper =
+        ActivityQueryHelper<Queryable> activityQueryHelper =
                 new ActivityQueryHelper<>(mQuery);
 
         activityQueryHelper.isSameClassAs(CLASS_1);
@@ -70,7 +69,7 @@
 
     @Test
     public void matches_className_doesMatch_returnsTrue() {
-        ActivityQueryHelper<CustomEvent.CustomEventQuery> activityQueryHelper =
+        ActivityQueryHelper<Queryable> activityQueryHelper =
                 new ActivityQueryHelper<>(mQuery);
 
         activityQueryHelper.className().isEqualTo(CLASS_1_CLASS_NAME);
@@ -80,7 +79,7 @@
 
     @Test
     public void matches_className_doesNotMatch_returnsFalse() {
-        ActivityQueryHelper<CustomEvent.CustomEventQuery> activityQueryHelper =
+        ActivityQueryHelper<Queryable> activityQueryHelper =
                 new ActivityQueryHelper<>(mQuery);
 
         activityQueryHelper.className().isEqualTo(CLASS_1_CLASS_NAME);
@@ -90,7 +89,7 @@
 
     @Test
     public void matches_simpleName_doesMatch_returnsTrue() {
-        ActivityQueryHelper<CustomEvent.CustomEventQuery> activityQueryHelper =
+        ActivityQueryHelper<Queryable> activityQueryHelper =
                 new ActivityQueryHelper<>(mQuery);
 
         activityQueryHelper.simpleName().isEqualTo(CLASS_1_SIMPLE_NAME);
@@ -100,7 +99,7 @@
 
     @Test
     public void matches_simpleName_doesNotMatch_returnsFalse() {
-        ActivityQueryHelper<CustomEvent.CustomEventQuery> activityQueryHelper =
+        ActivityQueryHelper<Queryable> activityQueryHelper =
                 new ActivityQueryHelper<>(mQuery);
 
         activityQueryHelper.simpleName().isEqualTo(CLASS_1_SIMPLE_NAME);
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/BundleKeyQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/BundleKeyQueryHelperTest.java
similarity index 81%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/BundleKeyQueryHelperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/BundleKeyQueryHelperTest.java
index 9283aba..9557bcb 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/BundleKeyQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/BundleKeyQueryHelperTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Bundle;
 
-import com.android.eventlib.events.CustomEvent;
+import com.android.queryable.Queryable;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -36,8 +36,7 @@
     private static final String STRING_VALUE = "String";
     private static final String DIFFERENT_STRING_VALUE = "String2";
 
-    private final CustomEvent.CustomEventQuery mQuery =
-            CustomEvent.queryPackage("testPackage"); // package is not used
+    private final Queryable mQuery = null;
     private final Bundle mBundle = new Bundle();
     private final Bundle mBundle2 = new Bundle();
     private final Serializable mSerializable = "SerializableString";
@@ -45,7 +44,7 @@
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
-        BundleKeyQueryHelper<CustomEvent.CustomEventQuery> bundleKeyQueryHelper =
+        BundleKeyQueryHelper<Queryable> bundleKeyQueryHelper =
                 new BundleKeyQueryHelper<>(mQuery);
 
         assertThat(bundleKeyQueryHelper.matches(mBundle, KEY)).isTrue();
@@ -54,7 +53,7 @@
     @Test
     public void matches_stringValueRestriction_meetsRestriction_returnsTrue() {
         mBundle.putString(KEY, STRING_VALUE);
-        BundleKeyQueryHelper<CustomEvent.CustomEventQuery> bundleKeyQueryHelper =
+        BundleKeyQueryHelper<Queryable> bundleKeyQueryHelper =
                 new BundleKeyQueryHelper<>(mQuery);
 
         bundleKeyQueryHelper.stringValue().isEqualTo(STRING_VALUE);
@@ -65,7 +64,7 @@
     @Test
     public void matches_stringValueRestriction_doesNotMeetRestriction_returnsFalse() {
         mBundle.putString(KEY, STRING_VALUE);
-        BundleKeyQueryHelper<CustomEvent.CustomEventQuery> bundleKeyQueryHelper =
+        BundleKeyQueryHelper<Queryable> bundleKeyQueryHelper =
                 new BundleKeyQueryHelper<>(mQuery);
 
         bundleKeyQueryHelper.stringValue().isEqualTo(DIFFERENT_STRING_VALUE);
@@ -77,7 +76,7 @@
     public void matches_bundleValueRestriction_meetsRestriction_returnsTrue() {
         mBundle.putBundle(KEY, mBundle2);
         mBundle2.putString(KEY2, STRING_VALUE);
-        BundleKeyQueryHelper<CustomEvent.CustomEventQuery> bundleKeyQueryHelper =
+        BundleKeyQueryHelper<Queryable> bundleKeyQueryHelper =
                 new BundleKeyQueryHelper<>(mQuery);
 
         bundleKeyQueryHelper.bundleValue().key(KEY2).exists();
@@ -89,7 +88,7 @@
     public void matches_bundleValueRestriction_doesNotMeetRestriction_returnsFalse() {
         mBundle.putBundle(KEY, mBundle2);
         mBundle2.remove(KEY2);
-        BundleKeyQueryHelper<CustomEvent.CustomEventQuery> bundleKeyQueryHelper =
+        BundleKeyQueryHelper<Queryable> bundleKeyQueryHelper =
                 new BundleKeyQueryHelper<>(mQuery);
 
         bundleKeyQueryHelper.bundleValue().key(KEY2).exists();
@@ -100,7 +99,7 @@
     @Test
     public void matches_serializableValueRestriction_meetsRestriction_returnsTrue() {
         mBundle.putSerializable(KEY, mSerializable);
-        BundleKeyQueryHelper<CustomEvent.CustomEventQuery> bundleKeyQueryHelper =
+        BundleKeyQueryHelper<Queryable> bundleKeyQueryHelper =
                 new BundleKeyQueryHelper<>(mQuery);
 
         bundleKeyQueryHelper.serializableValue().isEqualTo(mSerializable);
@@ -111,7 +110,7 @@
     @Test
     public void matches_serializableValueRestriction_doesNotMeetRestriction_returnsFalse() {
         mBundle.putSerializable(KEY, mSerializable);
-        BundleKeyQueryHelper<CustomEvent.CustomEventQuery> bundleKeyQueryHelper =
+        BundleKeyQueryHelper<Queryable> bundleKeyQueryHelper =
                 new BundleKeyQueryHelper<>(mQuery);
 
         bundleKeyQueryHelper.serializableValue().isEqualTo(mDifferentSerializable);
@@ -122,7 +121,7 @@
     @Test
     public void matches_existsRestriction_meetsRestriction_returnsTrue() {
         mBundle.putString(KEY, STRING_VALUE);
-        BundleKeyQueryHelper<CustomEvent.CustomEventQuery> bundleKeyQueryHelper =
+        BundleKeyQueryHelper<Queryable> bundleKeyQueryHelper =
                 new BundleKeyQueryHelper<>(mQuery);
 
         bundleKeyQueryHelper.exists();
@@ -133,7 +132,7 @@
     @Test
     public void matches_existsRestriction_doesNotMeetRestriction_returnsFalse() {
         mBundle.remove(KEY);
-        BundleKeyQueryHelper<CustomEvent.CustomEventQuery> bundleKeyQueryHelper =
+        BundleKeyQueryHelper<Queryable> bundleKeyQueryHelper =
                 new BundleKeyQueryHelper<>(mQuery);
 
         bundleKeyQueryHelper.exists();
@@ -144,7 +143,7 @@
     @Test
     public void matches_doesNotExistRestriction_meetsRestriction_returnsTrue() {
         mBundle.remove(KEY);
-        BundleKeyQueryHelper<CustomEvent.CustomEventQuery> bundleKeyQueryHelper =
+        BundleKeyQueryHelper<Queryable> bundleKeyQueryHelper =
                 new BundleKeyQueryHelper<>(mQuery);
 
         bundleKeyQueryHelper.doesNotExist();
@@ -155,7 +154,7 @@
     @Test
     public void matches_doesNotExistRestriction_doesNotMeetRestriction_returnsFalse() {
         mBundle.putString(KEY, STRING_VALUE);
-        BundleKeyQueryHelper<CustomEvent.CustomEventQuery> bundleKeyQueryHelper =
+        BundleKeyQueryHelper<Queryable> bundleKeyQueryHelper =
                 new BundleKeyQueryHelper<>(mQuery);
 
         bundleKeyQueryHelper.doesNotExist();
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/BundleQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/BundleQueryHelperTest.java
similarity index 80%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/BundleQueryHelperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/BundleQueryHelperTest.java
index 12d9b95..bd150bb 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/BundleQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/BundleQueryHelperTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Bundle;
 
-import com.android.eventlib.events.CustomEvent;
+import com.android.queryable.Queryable;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -33,13 +33,12 @@
     private static final String KEY2 = "Key2";
     private static final String STRING_VALUE = "value";
 
-    private final CustomEvent.CustomEventQuery mQuery =
-            CustomEvent.queryPackage("testPackage"); // package is not used
+    private final Queryable mQuery = null;
     private final Bundle mBundle = new Bundle();
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
-        BundleQueryHelper<CustomEvent.CustomEventQuery> bundleQueryHelper =
+        BundleQueryHelper<Queryable> bundleQueryHelper =
                 new BundleQueryHelper<>(mQuery);
 
         assertThat(bundleQueryHelper.matches(mBundle)).isTrue();
@@ -48,7 +47,7 @@
     @Test
     public void matches_restrictionOnOneKey_restrictionIsMet_returnsTrue() {
         mBundle.putString(KEY, STRING_VALUE);
-        BundleQueryHelper<CustomEvent.CustomEventQuery> bundleQueryHelper =
+        BundleQueryHelper<Queryable> bundleQueryHelper =
                 new BundleQueryHelper<>(mQuery);
 
         bundleQueryHelper.key(KEY).exists();
@@ -59,7 +58,7 @@
     @Test
     public void matches_restrictionOnOneKey_restrictionIsNotMet_returnsFalse() {
         mBundle.putString(KEY, STRING_VALUE);
-        BundleQueryHelper<CustomEvent.CustomEventQuery> bundleQueryHelper =
+        BundleQueryHelper<Queryable> bundleQueryHelper =
                 new BundleQueryHelper<>(mQuery);
 
         bundleQueryHelper.key(KEY).doesNotExist();
@@ -71,7 +70,7 @@
     public void matches_restrictionOnMultipleKeys_oneRestrictionIsNotMet_returnsFalse() {
         mBundle.putString(KEY, STRING_VALUE);
         mBundle.remove(KEY2);
-        BundleQueryHelper<CustomEvent.CustomEventQuery> bundleQueryHelper =
+        BundleQueryHelper<Queryable> bundleQueryHelper =
                 new BundleQueryHelper<>(mQuery);
 
         bundleQueryHelper.key(KEY).exists();
@@ -83,7 +82,7 @@
     @Test
     public void matches_restrictionOnNonExistingKey_returnsFalse() {
         mBundle.remove(KEY);
-        BundleQueryHelper<CustomEvent.CustomEventQuery> bundleQueryHelper =
+        BundleQueryHelper<Queryable> bundleQueryHelper =
                 new BundleQueryHelper<>(mQuery);
 
         bundleQueryHelper.key(KEY).stringValue().isEqualTo(STRING_VALUE);
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/ClassQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ClassQueryHelperTest.java
similarity index 80%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/ClassQueryHelperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ClassQueryHelperTest.java
index 175204e..21bc096 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/ClassQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/ClassQueryHelperTest.java
@@ -14,14 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.app.Activity;
 
 import com.android.eventlib.events.CustomEvent;
-import com.android.eventlib.info.ClassInfo;
+import com.android.queryable.Queryable;
+import com.android.queryable.info.ClassInfo;
+import com.android.queryable.queries.ClassQueryHelper;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -29,8 +31,7 @@
 
 @RunWith(JUnit4.class)
 public class ClassQueryHelperTest {
-    private final CustomEvent.CustomEventQuery mQuery =
-            CustomEvent.queryPackage("testPackage"); // package is not used
+    private final Queryable mQuery = null;
 
     private static final Class<?> CLASS_1 = Activity.class;
     private static final ClassInfo CLASS_1_CLASS_INFO = new ClassInfo(CLASS_1);
@@ -40,7 +41,7 @@
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
-        ClassQueryHelper<CustomEvent.CustomEventQuery> classQueryHelper =
+        ClassQueryHelper<Queryable> classQueryHelper =
                 new ClassQueryHelper<>(mQuery);
 
         assertThat(classQueryHelper.matches(CLASS_1_CLASS_INFO)).isTrue();
@@ -48,7 +49,7 @@
 
     @Test
     public void matches_isSameClassAs_doesMatch_returnsTrue() {
-        ClassQueryHelper<CustomEvent.CustomEventQuery> classQueryHelper =
+        ClassQueryHelper<Queryable> classQueryHelper =
                 new ClassQueryHelper<>(mQuery);
 
         classQueryHelper.isSameClassAs(CLASS_1);
@@ -58,7 +59,7 @@
 
     @Test
     public void matches_isSameClassAs_doesNotMatch_returnsFalse() {
-        ClassQueryHelper<CustomEvent.CustomEventQuery> classQueryHelper =
+        ClassQueryHelper<Queryable> classQueryHelper =
                 new ClassQueryHelper<>(mQuery);
 
         classQueryHelper.isSameClassAs(CLASS_1);
@@ -68,7 +69,7 @@
 
     @Test
     public void matches_className_doesMatch_returnsTrue() {
-        ClassQueryHelper<CustomEvent.CustomEventQuery> classQueryHelper =
+        ClassQueryHelper<Queryable> classQueryHelper =
                 new ClassQueryHelper<>(mQuery);
 
         classQueryHelper.className().isEqualTo(CLASS_1_CLASS_NAME);
@@ -78,7 +79,7 @@
 
     @Test
     public void matches_className_doesNotMatch_returnsFalse() {
-        ClassQueryHelper<CustomEvent.CustomEventQuery> classQueryHelper =
+        ClassQueryHelper<Queryable> classQueryHelper =
                 new ClassQueryHelper<>(mQuery);
 
         classQueryHelper.className().isEqualTo(CLASS_1_CLASS_NAME);
@@ -88,7 +89,7 @@
 
     @Test
     public void matches_simpleName_doesMatch_returnsTrue() {
-        ClassQueryHelper<CustomEvent.CustomEventQuery> classQueryHelper =
+        ClassQueryHelper<Queryable> classQueryHelper =
                 new ClassQueryHelper<>(mQuery);
 
         classQueryHelper.simpleName().isEqualTo(CLASS_1_SIMPLE_NAME);
@@ -98,7 +99,7 @@
 
     @Test
     public void matches_simpleName_doesNotMatch_returnsFalse() {
-        ClassQueryHelper<CustomEvent.CustomEventQuery> classQueryHelper =
+        ClassQueryHelper<Queryable> classQueryHelper =
                 new ClassQueryHelper<>(mQuery);
 
         classQueryHelper.simpleName().isEqualTo(CLASS_1_SIMPLE_NAME);
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/IntegerQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/IntegerQueryHelperTest.java
similarity index 78%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/IntegerQueryHelperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/IntegerQueryHelperTest.java
index 528e9a5..f2b7e3d 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/IntegerQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/IntegerQueryHelperTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import com.android.eventlib.events.CustomEvent;
+import com.android.queryable.Queryable;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -27,15 +27,14 @@
 @RunWith(JUnit4.class)
 public class IntegerQueryHelperTest {
 
-    private final CustomEvent.CustomEventQuery mQuery =
-            CustomEvent.queryPackage("testPackage"); // package is not used
+    private final Queryable mQuery = null;
     private static final int INTEGER_VALUE = 100;
     private static final int GREATER_VALUE = 200;
     private static final int LESS_VALUE = 50;
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         assertThat(integerQueryHelper.matches(INTEGER_VALUE)).isTrue();
@@ -43,7 +42,7 @@
 
     @Test
     public void matches_isEqualTo_meetsRestriction_returnsTrue() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isEqualTo(INTEGER_VALUE);
@@ -53,7 +52,7 @@
 
     @Test
     public void matches_isEqualTo_doesNotMeetRestriction_returnsFalse() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isEqualTo(INTEGER_VALUE);
@@ -63,7 +62,7 @@
 
     @Test
     public void matches_isGreaterThan_meetsRestriction_returnsTrue() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isGreaterThan(INTEGER_VALUE);
@@ -73,7 +72,7 @@
 
     @Test
     public void matches_isGreaterThan_doesNotMeetRestriction_returnsFalse() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isGreaterThan(INTEGER_VALUE);
@@ -83,7 +82,7 @@
 
     @Test
     public void matches_isGreaterThanOrEqualTo_greaterThan_returnsTrue() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isGreaterThanOrEqualTo(INTEGER_VALUE);
@@ -93,7 +92,7 @@
 
     @Test
     public void matches_isGreaterThanOrEqualTo_equalTo_returnsTrue() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isGreaterThanOrEqualTo(INTEGER_VALUE);
@@ -103,7 +102,7 @@
 
     @Test
     public void matches_isGreaterThanOrEqualTo_doesNotMeetRestriction_returnsFalse() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isGreaterThanOrEqualTo(INTEGER_VALUE);
@@ -113,7 +112,7 @@
 
     @Test
     public void matches_isLessThan_meetsRestriction_returnsTrue() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isLessThan(INTEGER_VALUE);
@@ -123,7 +122,7 @@
 
     @Test
     public void matches_isLessThan_doesNotMeetRestriction_returnsFalse() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isLessThan(INTEGER_VALUE);
@@ -133,7 +132,7 @@
 
     @Test
     public void matches_isLessThanOrEqualTo_lessThan_returnsTrue() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isLessThanOrEqualTo(INTEGER_VALUE);
@@ -143,7 +142,7 @@
 
     @Test
     public void matches_isLessThanOrEqualTo_equalTo_returnsTrue() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isLessThanOrEqualTo(INTEGER_VALUE);
@@ -153,7 +152,7 @@
 
     @Test
     public void matches_isLessThanOrEqualTo_doesNotMeetRestriction_returnsFalse() {
-        IntegerQueryHelper<CustomEvent.CustomEventQuery> integerQueryHelper =
+        IntegerQueryHelper<Queryable> integerQueryHelper =
                 new IntegerQueryHelper<>(mQuery);
 
         integerQueryHelper.isLessThanOrEqualTo(INTEGER_VALUE);
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/IntentQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/IntentQueryHelperTest.java
similarity index 81%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/IntentQueryHelperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/IntentQueryHelperTest.java
index e815479..45da9f4 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/IntentQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/IntentQueryHelperTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Intent;
 
-import com.android.eventlib.events.CustomEvent;
+import com.android.queryable.Queryable;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -29,15 +29,14 @@
 @RunWith(JUnit4.class)
 public class IntentQueryHelperTest {
 
-    private final CustomEvent.CustomEventQuery mQuery =
-            CustomEvent.queryPackage("testPackage"); // package is not used
+    private final Queryable mQuery = null;
     private static final String STRING_VALUE = "String";
     private static final String DIFFERENT_STRING_VALUE = "String2";
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
         Intent intent = new Intent();
-        IntentQueryHelper<CustomEvent.CustomEventQuery> intentQueryHelper =
+        IntentQueryHelper<Queryable> intentQueryHelper =
                 new IntentQueryHelper<>(mQuery);
 
         assertThat(intentQueryHelper.matches(intent)).isTrue();
@@ -47,7 +46,7 @@
     public void matches_action_meetsRestriction_returnsTrue() {
         Intent intent = new Intent();
         intent.setAction(STRING_VALUE);
-        IntentQueryHelper<CustomEvent.CustomEventQuery> intentQueryHelper =
+        IntentQueryHelper<Queryable> intentQueryHelper =
                 new IntentQueryHelper<>(mQuery);
 
         intentQueryHelper.action().isEqualTo(STRING_VALUE);
@@ -59,7 +58,7 @@
     public void matches_action_doesNotMeetRestriction_returnsFalse() {
         Intent intent = new Intent();
         intent.setAction(STRING_VALUE);
-        IntentQueryHelper<CustomEvent.CustomEventQuery> intentQueryHelper =
+        IntentQueryHelper<Queryable> intentQueryHelper =
                 new IntentQueryHelper<>(mQuery);
 
         intentQueryHelper.action().isEqualTo(DIFFERENT_STRING_VALUE);
@@ -71,7 +70,7 @@
     public void matches_extras_meetsRestriction_returnsTrue() {
         Intent intent = new Intent();
         intent.putExtra(/* key= */ STRING_VALUE, /* value= */ STRING_VALUE);
-        IntentQueryHelper<CustomEvent.CustomEventQuery> intentQueryHelper =
+        IntentQueryHelper<Queryable> intentQueryHelper =
                 new IntentQueryHelper<>(mQuery);
 
         intentQueryHelper.extras().key(STRING_VALUE).stringValue().isEqualTo(STRING_VALUE);
@@ -83,7 +82,7 @@
     public void matches_extras_doesNotMeetRestriction_returnsFalse() {
         Intent intent = new Intent();
         intent.putExtra(/* key= */ STRING_VALUE, /* value= */ STRING_VALUE);
-        IntentQueryHelper<CustomEvent.CustomEventQuery> intentQueryHelper =
+        IntentQueryHelper<Queryable> intentQueryHelper =
                 new IntentQueryHelper<>(mQuery);
 
         intentQueryHelper.extras().key(STRING_VALUE).stringValue()
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/PersistableBundleKeyQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/PersistableBundleKeyQueryHelperTest.java
similarity index 84%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/PersistableBundleKeyQueryHelperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/PersistableBundleKeyQueryHelperTest.java
index a587512..e461700 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/PersistableBundleKeyQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/PersistableBundleKeyQueryHelperTest.java
@@ -14,21 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.os.Bundle;
 import android.os.PersistableBundle;
 
-import com.android.eventlib.events.CustomEvent;
+import com.android.queryable.Queryable;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
-import java.io.Serializable;
-
 @RunWith(JUnit4.class)
 public class PersistableBundleKeyQueryHelperTest {
 
@@ -37,14 +34,13 @@
     private static final String STRING_VALUE = "String";
     private static final String DIFFERENT_STRING_VALUE = "String2";
 
-    private final CustomEvent.CustomEventQuery mQuery =
-            CustomEvent.queryPackage("testPackage"); // package is not used
+    private final Queryable mQuery = null;
     private final PersistableBundle mPersistableBundle = new PersistableBundle();
     private final PersistableBundle mPersistableBundle2 = new PersistableBundle();
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
-        PersistableBundleKeyQueryHelper<CustomEvent.CustomEventQuery>
+        PersistableBundleKeyQueryHelper<Queryable>
                 persistableBundleKeyQueryHelper = new PersistableBundleKeyQueryHelper<>(mQuery);
 
         assertThat(persistableBundleKeyQueryHelper.matches(mPersistableBundle, KEY)).isTrue();
@@ -53,7 +49,7 @@
     @Test
     public void matches_stringValueRestriction_meetsRestriction_returnsTrue() {
         mPersistableBundle.putString(KEY, STRING_VALUE);
-        PersistableBundleKeyQueryHelper<CustomEvent.CustomEventQuery>
+        PersistableBundleKeyQueryHelper<Queryable>
                 persistableBundleKeyQueryHelper = new PersistableBundleKeyQueryHelper<>(mQuery);
 
         persistableBundleKeyQueryHelper.stringValue().isEqualTo(STRING_VALUE);
@@ -64,7 +60,7 @@
     @Test
     public void matches_stringValueRestriction_doesNotMeetRestriction_returnsFalse() {
         mPersistableBundle.putString(KEY, STRING_VALUE);
-        PersistableBundleKeyQueryHelper<CustomEvent.CustomEventQuery>
+        PersistableBundleKeyQueryHelper<Queryable>
                 persistableBundleKeyQueryHelper = new PersistableBundleKeyQueryHelper<>(mQuery);
 
         persistableBundleKeyQueryHelper.stringValue().isEqualTo(DIFFERENT_STRING_VALUE);
@@ -76,7 +72,7 @@
     public void matches_persistableBundleValueRestriction_meetsRestriction_returnsTrue() {
         mPersistableBundle.putPersistableBundle(KEY, mPersistableBundle2);
         mPersistableBundle2.putString(KEY2, STRING_VALUE);
-        PersistableBundleKeyQueryHelper<CustomEvent.CustomEventQuery>
+        PersistableBundleKeyQueryHelper<Queryable>
                 persistableBundleKeyQueryHelper = new PersistableBundleKeyQueryHelper<>(mQuery);
 
         persistableBundleKeyQueryHelper.persistableBundleValue().key(KEY2).exists();
@@ -88,7 +84,7 @@
     public void matches_persistableBundleValueRestriction_doesNotMeetRestriction_returnsFalse() {
         mPersistableBundle.putPersistableBundle(KEY, mPersistableBundle2);
         mPersistableBundle2.remove(KEY2);
-        PersistableBundleKeyQueryHelper<CustomEvent.CustomEventQuery>
+        PersistableBundleKeyQueryHelper<Queryable>
                 persistableBundleKeyQueryHelper = new PersistableBundleKeyQueryHelper<>(mQuery);
 
         persistableBundleKeyQueryHelper.persistableBundleValue().key(KEY2).exists();
@@ -99,7 +95,7 @@
     @Test
     public void matches_existsRestriction_meetsRestriction_returnsTrue() {
         mPersistableBundle.putString(KEY, STRING_VALUE);
-        PersistableBundleKeyQueryHelper<CustomEvent.CustomEventQuery>
+        PersistableBundleKeyQueryHelper<Queryable>
                 persistableBundleKeyQueryHelper = new PersistableBundleKeyQueryHelper<>(mQuery);
 
         persistableBundleKeyQueryHelper.exists();
@@ -110,7 +106,7 @@
     @Test
     public void matches_existsRestriction_doesNotMeetRestriction_returnsFalse() {
         mPersistableBundle.remove(KEY);
-        PersistableBundleKeyQueryHelper<CustomEvent.CustomEventQuery>
+        PersistableBundleKeyQueryHelper<Queryable>
                 persistableBundleKeyQueryHelper = new PersistableBundleKeyQueryHelper<>(mQuery);
 
         persistableBundleKeyQueryHelper.exists();
@@ -121,7 +117,7 @@
     @Test
     public void matches_doesNotExistRestriction_meetsRestriction_returnsTrue() {
         mPersistableBundle.remove(KEY);
-        PersistableBundleKeyQueryHelper<CustomEvent.CustomEventQuery>
+        PersistableBundleKeyQueryHelper<Queryable>
                 persistableBundleKeyQueryHelper = new PersistableBundleKeyQueryHelper<>(mQuery);
 
         persistableBundleKeyQueryHelper.doesNotExist();
@@ -132,7 +128,7 @@
     @Test
     public void matches_doesNotExistRestriction_doesNotMeetRestriction_returnsFalse() {
         mPersistableBundle.putString(KEY, STRING_VALUE);
-        PersistableBundleKeyQueryHelper<CustomEvent.CustomEventQuery>
+        PersistableBundleKeyQueryHelper<Queryable>
                 persistableBundleKeyQueryHelper = new PersistableBundleKeyQueryHelper<>(mQuery);
 
         persistableBundleKeyQueryHelper.doesNotExist();
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/PersistableBundleQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/PersistableBundleQueryHelperTest.java
similarity index 79%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/PersistableBundleQueryHelperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/PersistableBundleQueryHelperTest.java
index 39f11ec..6379bee 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/PersistableBundleQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/PersistableBundleQueryHelperTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.PersistableBundle;
 
-import com.android.eventlib.events.CustomEvent;
+import com.android.queryable.Queryable;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -32,13 +32,12 @@
     private static final String KEY2 = "Key2";
     private static final String STRING_VALUE = "value";
 
-    private final CustomEvent.CustomEventQuery mQuery =
-            CustomEvent.queryPackage("testPackage"); // package is not used
+    private final Queryable mQuery = null;
     private final PersistableBundle mPersistableBundle = new PersistableBundle();
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
-        PersistableBundleQueryHelper<CustomEvent.CustomEventQuery> persistableBundleQueryHelper =
+        PersistableBundleQueryHelper<Queryable> persistableBundleQueryHelper =
                 new PersistableBundleQueryHelper<>(mQuery);
 
         assertThat(persistableBundleQueryHelper.matches(mPersistableBundle)).isTrue();
@@ -47,7 +46,7 @@
     @Test
     public void matches_restrictionOnOneKey_restrictionIsMet_returnsTrue() {
         mPersistableBundle.putString(KEY, STRING_VALUE);
-        PersistableBundleQueryHelper<CustomEvent.CustomEventQuery> persistableBundleQueryHelper =
+        PersistableBundleQueryHelper<Queryable> persistableBundleQueryHelper =
                 new PersistableBundleQueryHelper<>(mQuery);
 
         persistableBundleQueryHelper.key(KEY).exists();
@@ -58,7 +57,7 @@
     @Test
     public void matches_restrictionOnOneKey_restrictionIsNotMet_returnsFalse() {
         mPersistableBundle.putString(KEY, STRING_VALUE);
-        PersistableBundleQueryHelper<CustomEvent.CustomEventQuery> persistableBundleQueryHelper =
+        PersistableBundleQueryHelper<Queryable> persistableBundleQueryHelper =
                 new PersistableBundleQueryHelper<>(mQuery);
 
         persistableBundleQueryHelper.key(KEY).doesNotExist();
@@ -70,7 +69,7 @@
     public void matches_restrictionOnMultipleKeys_oneRestrictionIsNotMet_returnsFalse() {
         mPersistableBundle.putString(KEY, STRING_VALUE);
         mPersistableBundle.remove(KEY2);
-        PersistableBundleQueryHelper<CustomEvent.CustomEventQuery> persistableBundleQueryHelper =
+        PersistableBundleQueryHelper<Queryable> persistableBundleQueryHelper =
                 new PersistableBundleQueryHelper<>(mQuery);
 
         persistableBundleQueryHelper.key(KEY).exists();
@@ -82,7 +81,7 @@
     @Test
     public void matches_restrictionOnNonExistingKey_returnsFalse() {
         mPersistableBundle.remove(KEY);
-        PersistableBundleQueryHelper<CustomEvent.CustomEventQuery> persistableBundleQueryHelper =
+        PersistableBundleQueryHelper<Queryable> persistableBundleQueryHelper =
                 new PersistableBundleQueryHelper<>(mQuery);
 
         persistableBundleQueryHelper.key(KEY).stringValue().isEqualTo(STRING_VALUE);
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/SerializableQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/SerializableQueryHelperTest.java
similarity index 78%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/SerializableQueryHelperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/SerializableQueryHelperTest.java
index a1f23b1..2ddc136 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/SerializableQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/SerializableQueryHelperTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import com.android.eventlib.events.CustomEvent;
+import com.android.queryable.Queryable;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -29,14 +29,13 @@
 @RunWith(JUnit4.class)
 public class SerializableQueryHelperTest {
 
-    private final CustomEvent.CustomEventQuery mQuery =
-            CustomEvent.queryPackage("testPackage"); // package is not used
+    private final Queryable mQuery = null;
     private final Serializable mSerializable = "SerializableString";
     private final Serializable mDifferentSerializable = "SerializableString2";
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
-        SerializableQueryHelper<CustomEvent.CustomEventQuery> serializableQueryHelper =
+        SerializableQueryHelper<Queryable> serializableQueryHelper =
                 new SerializableQueryHelper<>(mQuery);
 
         assertThat(serializableQueryHelper.matches(mSerializable)).isTrue();
@@ -44,7 +43,7 @@
 
     @Test
     public void matches_isEqualTo_meetsRestriction_returnsTrue() {
-        SerializableQueryHelper<CustomEvent.CustomEventQuery> serializableQueryHelper =
+        SerializableQueryHelper<Queryable> serializableQueryHelper =
                 new SerializableQueryHelper<>(mQuery);
 
         serializableQueryHelper.isEqualTo(mSerializable);
@@ -54,7 +53,7 @@
 
     @Test
     public void matches_isEqualTo_doesNotMeetRestriction_returnsFalse() {
-        SerializableQueryHelper<CustomEvent.CustomEventQuery> serializableQueryHelper =
+        SerializableQueryHelper<Queryable> serializableQueryHelper =
                 new SerializableQueryHelper<>(mQuery);
 
         serializableQueryHelper.isEqualTo(mDifferentSerializable);
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/StringQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/StringQueryHelperTest.java
similarity index 78%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/StringQueryHelperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/StringQueryHelperTest.java
index 2cb6b16..9797b8c 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/StringQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/StringQueryHelperTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import com.android.eventlib.events.CustomEvent;
+import com.android.queryable.Queryable;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -27,14 +27,13 @@
 @RunWith(JUnit4.class)
 public class StringQueryHelperTest {
 
-    private final CustomEvent.CustomEventQuery mQuery =
-            CustomEvent.queryPackage("testPackage"); // package is not used
+    private final Queryable mQuery = null;
     private static final String STRING_VALUE = "String";
     private static final String DIFFERENT_STRING_VALUE = "String2";
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
-        StringQueryHelper<CustomEvent.CustomEventQuery> stringQueryHelper =
+        StringQueryHelper<Queryable> stringQueryHelper =
                 new StringQueryHelper<>(mQuery);
 
         assertThat(stringQueryHelper.matches(STRING_VALUE)).isTrue();
@@ -42,7 +41,7 @@
 
     @Test
     public void matches_isEqualTo_meetsRestriction_returnsTrue() {
-        StringQueryHelper<CustomEvent.CustomEventQuery> stringQueryHelper =
+        StringQueryHelper<Queryable> stringQueryHelper =
                 new StringQueryHelper<>(mQuery);
 
         stringQueryHelper.isEqualTo(STRING_VALUE);
@@ -52,7 +51,7 @@
 
     @Test
     public void matches_isEqualTo_doesNotMeetRestriction_returnsFalse() {
-        StringQueryHelper<CustomEvent.CustomEventQuery> stringQueryHelper =
+        StringQueryHelper<Queryable> stringQueryHelper =
                 new StringQueryHelper<>(mQuery);
 
         stringQueryHelper.isEqualTo(DIFFERENT_STRING_VALUE);
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/UserHandleQueryHelperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/UserHandleQueryHelperTest.java
similarity index 78%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/UserHandleQueryHelperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/UserHandleQueryHelperTest.java
index 9b12586..941e5fa 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/queryhelpers/UserHandleQueryHelperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/queries/UserHandleQueryHelperTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.queryhelpers;
+package com.android.queryable.queries;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.UserHandle;
 
-import com.android.eventlib.events.CustomEvent;
+import com.android.queryable.Queryable;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -29,15 +29,14 @@
 @RunWith(JUnit4.class)
 public class UserHandleQueryHelperTest {
 
-    private final CustomEvent.CustomEventQuery mQuery =
-            CustomEvent.queryPackage("testPackage"); // package is not used
+    private final Queryable mQuery = null;
     private static final int USER_HANDLE_ID = 1;
     private static final UserHandle USER_HANDLE = UserHandle.of(USER_HANDLE_ID);
     private static final UserHandle DIFFERENT_USER_HANDLE = UserHandle.of(2);
 
     @Test
     public void matches_noRestrictions_returnsTrue() {
-        UserHandleQueryHelper<CustomEvent.CustomEventQuery> userHandleQueryHelper =
+        UserHandleQueryHelper<Queryable> userHandleQueryHelper =
                 new UserHandleQueryHelper<>(mQuery);
 
         assertThat(userHandleQueryHelper.matches(USER_HANDLE)).isTrue();
@@ -45,7 +44,7 @@
 
     @Test
     public void matches_isEqualTo_meetsRestriction_returnsTrue() {
-        UserHandleQueryHelper<CustomEvent.CustomEventQuery> userHandleQueryHelper =
+        UserHandleQueryHelper<Queryable> userHandleQueryHelper =
                 new UserHandleQueryHelper<>(mQuery);
 
         userHandleQueryHelper.isEqualTo(USER_HANDLE);
@@ -55,7 +54,7 @@
 
     @Test
     public void matches_isEqualTo_doesNotMeetRestriction_returnsFalse() {
-        UserHandleQueryHelper<CustomEvent.CustomEventQuery> userHandleQueryHelper =
+        UserHandleQueryHelper<Queryable> userHandleQueryHelper =
                 new UserHandleQueryHelper<>(mQuery);
 
         userHandleQueryHelper.isEqualTo(USER_HANDLE);
@@ -65,7 +64,7 @@
 
     @Test
     public void matches_id_meetsRestriction_returnsTrue() {
-        UserHandleQueryHelper<CustomEvent.CustomEventQuery> userHandleQueryHelper =
+        UserHandleQueryHelper<Queryable> userHandleQueryHelper =
                 new UserHandleQueryHelper<>(mQuery);
 
         userHandleQueryHelper.id().isEqualTo(USER_HANDLE_ID);
@@ -75,7 +74,7 @@
 
     @Test
     public void matches_id_doesNotMeetRestriction_returnsFalse() {
-        UserHandleQueryHelper<CustomEvent.CustomEventQuery> userHandleQueryHelper =
+        UserHandleQueryHelper<Queryable> userHandleQueryHelper =
                 new UserHandleQueryHelper<>(mQuery);
 
         userHandleQueryHelper.id().isEqualTo(USER_HANDLE_ID);
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/util/SerializableParcelWrapperTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/util/SerializableParcelWrapperTest.java
similarity index 97%
rename from common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/util/SerializableParcelWrapperTest.java
rename to common/device-side/bedstead/queryable/src/test/java/com/android/queryable/util/SerializableParcelWrapperTest.java
index fa73206..8ee103f 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/util/SerializableParcelWrapperTest.java
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/util/SerializableParcelWrapperTest.java
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.eventlib.util;
+package com.android.queryable.util;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Bundle;
 import android.os.Parcelable;
 
+import com.android.queryable.util.SerializableParcelWrapper;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
diff --git a/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java b/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java
index e003673..1bea8f4 100644
--- a/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java
+++ b/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java
@@ -122,4 +122,6 @@
     /** See {@link DevicePolicyManager#clearCrossProfileIntentFilters(ComponentName)}. */
     @RemoteDpcAutomaticAdmin void clearCrossProfileIntentFilters();
 
+    /** See {@link DevicePolicyManager#setPreferentialNetworkServiceEnabled(boolean)}. */
+    void setPreferentialNetworkServiceEnabled(boolean enabled);
 }
diff --git a/common/device-side/bedstead/remotedpc/src/library/test/java/com/android/bedstead/remotedpc/RemoteDpcTest.java b/common/device-side/bedstead/remotedpc/src/library/test/java/com/android/bedstead/remotedpc/RemoteDpcTest.java
index 584d1fa..ea05cc9 100644
--- a/common/device-side/bedstead/remotedpc/src/library/test/java/com/android/bedstead/remotedpc/RemoteDpcTest.java
+++ b/common/device-side/bedstead/remotedpc/src/library/test/java/com/android/bedstead/remotedpc/RemoteDpcTest.java
@@ -66,7 +66,8 @@
     @BeforeClass
     public static void setupClass() {
         sNonRemoteDpcTestApp = new TestAppProvider().query()
-                .withPackageName(DEVICE_ADMIN_TESTAPP_PACKAGE_NAME)
+                // TODO(scottjonathan): Query by feature not package name
+                .wherePackageName().isEqualTo(DEVICE_ADMIN_TESTAPP_PACKAGE_NAME)
                 .get();
 
         sNonRemoteDpcTestApp.install(sUser);
diff --git a/common/device-side/bedstead/testapp/Android.bp b/common/device-side/bedstead/testapp/Android.bp
index 7e4611d..347e120 100644
--- a/common/device-side/bedstead/testapp/Android.bp
+++ b/common/device-side/bedstead/testapp/Android.bp
@@ -30,6 +30,7 @@
     static_libs: [
         "Nene",
         "EventLib",
+        "Queryable",
         "TestApp_Annotations",
         "ConnectedAppsSDK",
         "ConnectedAppsSDK_Annotations",
diff --git a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppQueryBuilder.java b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppQueryBuilder.java
index cd50513..7445f3f 100644
--- a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppQueryBuilder.java
+++ b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppQueryBuilder.java
@@ -16,12 +16,17 @@
 
 package com.android.bedstead.testapp;
 
+import com.android.eventlib.events.activities.ActivityCreatedEvent;
+import com.android.queryable.Queryable;
+import com.android.queryable.queries.ActivityQueryHelper;
+import com.android.queryable.queries.StringQuery;
+import com.android.queryable.queries.StringQueryHelper;
+
 /** Builder for progressively building {@link TestApp} queries. */
-public final class TestAppQueryBuilder {
-    // TODO(scottjonathan): Consider how specific we can make this query builder - perhaps pull out
-    //  the queries from EventLib and use them here too
+public final class TestAppQueryBuilder implements Queryable {
     private final TestAppProvider mProvider;
-    private String mPackageName = null;
+
+    StringQueryHelper<TestAppQueryBuilder> mPackageName = new StringQueryHelper<>(this);
 
     TestAppQueryBuilder(TestAppProvider provider) {
         if (provider == null) {
@@ -37,12 +42,8 @@
      * are relying on features you know the {@link TestApp} with that package name has, query for
      * those features directly.
      */
-    public TestAppQueryBuilder withPackageName(String packageName) {
-        if (packageName == null) {
-            throw new NullPointerException();
-        }
-        mPackageName = packageName;
-        return this;
+    public StringQuery<TestAppQueryBuilder> wherePackageName() {
+        return mPackageName;
     }
 
     /**
@@ -57,7 +58,7 @@
 
     private TestAppDetails resolveQuery() {
         for (TestAppDetails details : mProvider.testApps()) {
-            if (mPackageName != null && !mPackageName.equals(details.mPackageName)) {
+            if (!matches(details)) {
                 continue;
             }
 
@@ -67,4 +68,12 @@
 
         throw new NotFoundException(this);
     }
+
+    private boolean matches(TestAppDetails details) {
+        if (!mPackageName.matches(details.mPackageName)) {
+            return false;
+        }
+
+        return true;
+    }
 }
diff --git a/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppProviderTest.java b/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppProviderTest.java
index 9ab3fe3..c4e78a3 100644
--- a/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppProviderTest.java
+++ b/common/device-side/bedstead/testapp/src/test/java/com/android/bedstead/testapp/TestAppProviderTest.java
@@ -44,7 +44,7 @@
     @Test
     public void get_queryMatches_returnsTestApp() {
         TestAppQueryBuilder query = mTestAppProvider.query()
-                .withPackageName(EXISTING_PACKAGENAME);
+                .wherePackageName().isEqualTo(EXISTING_PACKAGENAME);
 
         assertThat(query.get()).isNotNull();
     }
@@ -52,7 +52,7 @@
     @Test
     public void get_queryMatches_packageNameIsSet() {
         TestAppQueryBuilder query = mTestAppProvider.query()
-                .withPackageName(EXISTING_PACKAGENAME);
+                .wherePackageName().isEqualTo(EXISTING_PACKAGENAME);
 
         assertThat(query.get().packageName()).isEqualTo(EXISTING_PACKAGENAME);
     }
@@ -60,7 +60,7 @@
     @Test
     public void get_queryDoesNotMatch_throwsException() {
         TestAppQueryBuilder query = mTestAppProvider.query()
-                .withPackageName(NOT_EXISTING_PACKAGENAME);
+                .wherePackageName().isEqualTo(NOT_EXISTING_PACKAGENAME);
 
         assertThrows(NotFoundException.class, query::get);
     }
@@ -77,9 +77,9 @@
 
     @Test
     public void query_onlyReturnsTestAppOnce() {
-        mTestAppProvider.query().withPackageName(EXISTING_PACKAGENAME).get();
+        mTestAppProvider.query().wherePackageName().isEqualTo(EXISTING_PACKAGENAME).get();
 
-        TestAppQueryBuilder query = mTestAppProvider.query().withPackageName(EXISTING_PACKAGENAME);
+        TestAppQueryBuilder query = mTestAppProvider.query().wherePackageName().isEqualTo(EXISTING_PACKAGENAME);
 
         assertThrows(NotFoundException.class, query::get);
     }
diff --git a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchHostTestBase.java b/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchHostTestBase.java
index 7dd10d9f..203fa82 100644
--- a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchHostTestBase.java
+++ b/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchHostTestBase.java
@@ -29,6 +29,8 @@
     protected static final String TARGET_APK_A = "CtsAppSearchHostTestHelperA.apk";
     protected static final String TARGET_PKG_A = "android.appsearch.app.a";
     protected static final String TEST_CLASS_A = TARGET_PKG_A + ".AppSearchDeviceTest";
+    protected static final String TEST_STORAGE_AUGMENTER_CLASS_A =
+            TARGET_PKG_A + ".AppSearchStorageAugmenterDeviceTest";
     protected static final String TARGET_APK_B = "CtsAppSearchHostTestHelperB.apk";
     protected static final String TARGET_PKG_B = "android.appsearch.app.b";
     protected static final String TEST_CLASS_B = TARGET_PKG_B + ".AppSearchDeviceTest";
@@ -58,6 +60,13 @@
                 runDeviceTests(deviceTestRunOptions)).isTrue();
     }
 
+    protected void runStorageAugmenterDeviceTestAsUserInPkgA(@Nonnull String testMethod, int userId)
+            throws Exception {
+        assertWithMessage(testMethod + " failed").that(
+                runDeviceTests(getDevice(), TARGET_PKG_A, TEST_STORAGE_AUGMENTER_CLASS_A,
+                        testMethod, userId, DEFAULT_INSTRUMENTATION_TIMEOUT_MS)).isTrue();
+    }
+
     protected void runDeviceTestAsUserInPkgB(@Nonnull String testMethod, int userId)
             throws Exception {
         assertWithMessage(testMethod + " failed").that(
diff --git a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTest.java b/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTest.java
index 7627d90..1764cab 100644
--- a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTest.java
+++ b/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTest.java
@@ -111,4 +111,21 @@
         getDevice().startUser(mSecondaryUserId, /*waitFlag=*/true);
         runDeviceTestAsUserInPkgB("testGlobalGetDocuments_nonexist", mSecondaryUserId);
     }
+
+    @Test
+    public void testReadStorageInfoFromFile() throws Exception {
+        runDeviceTestAsUserInPkgA("testPutDocuments", mSecondaryUserId);
+
+        getDevice().stopUser(mSecondaryUserId, /*waitFlag=*/true, /*forceFlag=*/true);
+        getDevice().startUser(mSecondaryUserId, /*waitFlag=*/true);
+        // Write user's storage info into file while initializing AppSearchImpl.
+        runStorageAugmenterDeviceTestAsUserInPkgA("connectToAppSearch", mSecondaryUserId);
+
+        // Disconnect user from AppSearch. While AppSearchImpl doesn't exist for the user, user's
+        // storage info would be read from file.
+        getDevice().stopUser(mSecondaryUserId, /*waitFlag=*/true, /*forceFlag=*/true);
+        getDevice().startUser(mSecondaryUserId, /*waitFlag=*/true);
+
+        runStorageAugmenterDeviceTestAsUserInPkgA("testReadStorageInfo", mSecondaryUserId);
+    }
 }
diff --git a/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/src/android/appsearch/app/a/AppSearchStorageAugmenterDeviceTest.java b/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/src/android/appsearch/app/a/AppSearchStorageAugmenterDeviceTest.java
new file mode 100644
index 0000000..3e91498
--- /dev/null
+++ b/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/src/android/appsearch/app/a/AppSearchStorageAugmenterDeviceTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.appsearch.app.a;
+
+import static android.os.storage.StorageManager.UUID_DEFAULT;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.appsearch.AppSearchManager;
+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
+import android.content.Context;
+import android.os.UserHandle;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.server.appsearch.testing.AppSearchSessionShimImpl;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class AppSearchStorageAugmenterDeviceTest {
+
+    @Test
+    public void connectToAppSearch() throws Exception {
+        AppSearchSessionShimImpl.createSearchSession(
+                new AppSearchManager.SearchContext.Builder("dbName").build()).get();
+    }
+
+    @Test
+    public void testReadStorageInfo() throws Exception {
+        Context context = ApplicationProvider.getApplicationContext();
+        StorageStatsManager storageStatsManager =
+                context.getSystemService(StorageStatsManager.class);
+        String packageName = context.getPackageName();
+        UserHandle user = context.getUser();
+        int uid = android.os.Process.myUid();
+
+        // Query the storage info through AppSearchStorageStatsAugmenter.
+        StorageStats statsForPkg =
+                storageStatsManager.queryStatsForPackage(UUID_DEFAULT, packageName, user);
+        StorageStats statsForUid = storageStatsManager.queryStatsForUid(UUID_DEFAULT, uid);
+
+        assertThat(statsForPkg.getDataBytes()).isGreaterThan(0);
+        assertThat(statsForUid.getDataBytes()).isGreaterThan(0);
+    }
+}
diff --git a/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java b/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java
index ed87759..1d5ebcf 100644
--- a/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java
+++ b/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java
@@ -247,7 +247,7 @@
 
     // TODO(b/170263003): update this method after core framewokr's refactoring for proto
     private void waitUntilUserPermissionsIsReady(int userId) throws InterruptedException {
-        int napTimeSec = 10;
+        int napTimeSec = 20;
         CLog.i("Sleeping %ds to make permissions for user %d is ready", napTimeSec, userId);
         sleep(napTimeSec * 1_000);
     }
diff --git a/hostsidetests/edi/OWNERS b/hostsidetests/edi/OWNERS
index 855cee0..88c9013 100644
--- a/hostsidetests/edi/OWNERS
+++ b/hostsidetests/edi/OWNERS
@@ -5,4 +5,4 @@
 samlin@google.com
 
 # For cleanups and bug fixes
-satayev@google.com #{NEVER_SUGGEST}
+satayev@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/hostsidetests/scopedstorage/Android.bp b/hostsidetests/scopedstorage/Android.bp
index 2f9d826..fbfd706 100644
--- a/hostsidetests/scopedstorage/Android.bp
+++ b/hostsidetests/scopedstorage/Android.bp
@@ -21,8 +21,7 @@
     manifest: "ScopedStorageTestHelper/TestAppA.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    // TODO(b/187502983) Change to "31" once S SDK finalised
-    target_sdk_version: "10000",
+    target_sdk_version: "31",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -33,8 +32,7 @@
     manifest: "ScopedStorageTestHelper/TestAppB.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    // TODO(b/187502983) Change to "31" once S SDK finalised
-    target_sdk_version: "10000",
+    target_sdk_version: "31",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -45,8 +43,7 @@
     manifest: "ScopedStorageTestHelper/TestAppC.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    // TODO(b/187502983) Change to "31" once S SDK finalised
-    target_sdk_version: "10000",
+    target_sdk_version: "31",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -91,8 +88,7 @@
     manifest: "ScopedStorageTestHelper/TestAppFileManager.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    // TODO(b/187502983) Change to "31" once S SDK finalised
-    target_sdk_version: "10000",
+    target_sdk_version: "31",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -103,8 +99,7 @@
     manifest: "ScopedStorageTestHelper/TestAppFileManagerBypassDB.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    // TODO(b/187502983) Change to "31" once S SDK finalised
-    target_sdk_version: "10000",
+    target_sdk_version: "31",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -115,8 +110,7 @@
     manifest: "ScopedStorageTestHelper/TestAppSystemGalleryBypassDB.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    // TODO(b/187502983) Change to "31" once S SDK finalised
-    target_sdk_version: "10000",
+    target_sdk_version: "31",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -160,8 +154,7 @@
     compile_multilib: "both",
     test_suites: ["general-tests", "mts-mediaprovider", "cts"],
     sdk_version: "test_current",
-    // TODO(b/187502983) Change to "31" once S SDK finalised
-    target_sdk_version: "10000",
+    target_sdk_version: "31",
     min_sdk_version: "30",
     java_resources: [
         ":CtsScopedStorageTestAppA",
@@ -217,6 +210,17 @@
     test_config: "PublicVolumeTest.xml",
 }
 
+java_test_host {
+    name: "CtsAppCloningHostTest",
+    srcs:  [
+        "host/src/android/scopedstorage/cts/host/AppCloningHostTest.java",
+        "host/src/android/scopedstorage/cts/host/BaseHostTestCase.java"
+    ],
+    libs: ["cts-tradefed", "tradefed", "testng"],
+    test_suites: ["general-tests", "mts-mediaprovider", "cts"],
+    test_config: "AndroidTestAppCloning.xml",
+}
+
 android_test {
     name: "CtsScopedStorageDeviceOnlyTest",
     manifest: "device/AndroidManifest.xml",
@@ -226,8 +230,7 @@
     compile_multilib: "both",
     test_suites: ["device-tests", "mts-mediaprovider", "cts"],
     sdk_version: "test_current",
-    // TODO(b/187502983) Change to "31" once S SDK finalised
-    target_sdk_version: "10000",
+    target_sdk_version: "31",
     min_sdk_version: "30",
     libs: ["android.test.base", "android.test.mock", "android.test.runner",],
     java_resources: [
diff --git a/hostsidetests/scopedstorage/AndroidTestAppCloning.xml b/hostsidetests/scopedstorage/AndroidTestAppCloning.xml
new file mode 100644
index 0000000..03802f2
--- /dev/null
+++ b/hostsidetests/scopedstorage/AndroidTestAppCloning.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test for App cloning support with clone user profiles">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="framework" />
+    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <!-- TODO(b/169101565): change to secondary_user when fixed -->
+    <!-- Clone user profile is meant to exist only alongside a real system user.
+    It does not exist for a headless system user, or a secondary user -->
+    <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
+    <test class="com.android.tradefed.testtype.HostTest" >
+        <option name="class" value="android.scopedstorage.cts.host.AppCloningHostTest" />
+    </test>
+
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <option name="mainline-module-package-name" value="com.google.android.mediaprovider" />
+    </object>
+</configuration>
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/AppCloningHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/AppCloningHostTest.java
new file mode 100644
index 0000000..7f19369
--- /dev/null
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/AppCloningHostTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.scopedstorage.cts.host;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeFalse;
+
+import android.platform.test.annotations.AppModeFull;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.contentprovider.ContentProviderHandler;
+import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.util.CommandResult;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Runs the AppCloning tests.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+@AppModeFull
+public class AppCloningHostTest extends BaseHostTestCase {
+    private static final String APP_A = "CtsScopedStorageTestAppA.apk";
+    private static final String APP_A_PACKAGE = "android.scopedstorage.cts.testapp.A.withres";
+    private static final String APP_FOR_PVT_PACKAGE = "com.google.android.gms";
+    private static final String CONTENT_PROVIDER_URL = "content://android.tradefed.contentprovider";
+    private static final int APP_DATA_DIRECTORY_CREATION_TIMEOUT_MS = 20000;
+    private String mCloneUserId;
+    private ContentProviderHandler mContentProviderHandler;
+
+
+    @Before
+    public void setup() throws Exception {
+        assumeFalse("Device is in headless system user mode", isHeadlessSystemUserMode());
+
+        String output = executeShellCommand(
+                "pm create-user --profileOf 0 --user-type android.os.usertype.profile.CLONE "
+                        + "testUser");
+        mCloneUserId = output.substring(output.lastIndexOf(' ') + 1).replaceAll("[^0-9]", "");
+        assertThat(mCloneUserId).isNotEmpty();
+        CommandResult out = executeShellV2Command("am start-user -w %s", mCloneUserId);
+        assertThat(out.getStderr()).isEmpty();
+        mContentProviderHandler = new ContentProviderHandler(getDevice());
+        mContentProviderHandler.setUp();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        if (isHeadlessSystemUserMode()) return;
+        executeShellCommand("pm remove-user %s", mCloneUserId);
+    }
+
+    @Test
+    public void testInstallAppTwice() throws Exception {
+        installAppAsUser(APP_A, getCurrentUserId());
+        installAppAsUser(APP_A, Integer.valueOf(mCloneUserId));
+        uninstallPackage(APP_A_PACKAGE);
+    }
+
+    @Test
+    public void testCreateCloneUserFile() throws Exception {
+        // Check that the clone user directories exist
+        CommandResult out = runContentProviderCommand("query", mCloneUserId, "/sdcard", "");
+        assertThat(isSuccessful(out)).isTrue();
+        // Create a file on the clone user storage
+        out = executeShellV2Command("touch /sdcard/testFile.txt");
+        assertThat(isSuccessful(out)).isTrue();
+        out = runContentProviderCommand("write", mCloneUserId, "/sdcard/testFile.txt",
+                "< /sdcard/testFile.txt");
+        assertThat(isSuccessful(out)).isTrue();
+
+        // Check that the above created file exists on the clone user storage
+        out = runContentProviderCommand("query", mCloneUserId, "/sdcard/testFile.txt", "");
+        assertThat(isSuccessful(out)).isTrue();
+
+        // Cleanup the created file
+        out = runContentProviderCommand("delete", mCloneUserId, "/sdcard/testFile.txt", "");
+        assertThat(isSuccessful(out)).isTrue();
+    }
+
+    @Test
+    public void testPrivateAppDataDirectoryForCloneUser() throws Exception {
+        eventually(() -> {
+            assertThat(isPackageInstalled(APP_FOR_PVT_PACKAGE, mCloneUserId)).isTrue();
+        }, APP_DATA_DIRECTORY_CREATION_TIMEOUT_MS);
+    }
+
+    private void installAppAsUser(String packageFile, int userId)
+            throws TargetSetupError, DeviceNotAvailableException {
+        installPackageAsUser(packageFile, false, userId, "-t");
+    }
+
+    private CommandResult runContentProviderCommand(String commandType, String userId,
+            String relativePath, String args) throws Exception {
+        String fullUri = CONTENT_PROVIDER_URL + relativePath;
+        return executeShellV2Command("content %s --user %s --uri %s %s",
+                commandType, userId, fullUri, args);
+    }
+
+}
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/BaseHostTestCase.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/BaseHostTestCase.java
index 983cc66..bb2b6cc 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/BaseHostTestCase.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/BaseHostTestCase.java
@@ -16,24 +16,77 @@
 
 package android.scopedstorage.cts.host;
 
+import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.NativeDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
+
 
 abstract class BaseHostTestCase extends BaseHostJUnit4Test {
     private int mCurrentUserId = NativeDevice.INVALID_USER_ID;
+    private static final String ERROR_MESSAGE_TAG = "[ERROR]";
 
     protected String executeShellCommand(String cmd, Object... args) throws Exception {
         return getDevice().executeShellCommand(String.format(cmd, args));
     }
 
+    protected CommandResult executeShellV2Command(String cmd, Object... args) throws Exception {
+        return getDevice().executeShellV2Command(String.format(cmd, args));
+    }
+
+    protected boolean isPackageInstalled(String packageName, String userId) throws Exception {
+        return getDevice().isPackageInstalled(packageName, userId);
+    }
+
+    // TODO (b/174775905) remove after exposing the check from ITestDevice.
+    protected boolean isHeadlessSystemUserMode() throws DeviceNotAvailableException {
+        String result = getDevice()
+                .executeShellCommand("getprop ro.fw.mu.headless_system_user").trim();
+        return "true".equalsIgnoreCase(result);
+    }
+
+    protected static void eventually(ThrowingRunnable r, long timeoutMillis) {
+        long start = System.currentTimeMillis();
+
+        while (true) {
+            try {
+                r.run();
+                return;
+            } catch (Throwable e) {
+                if (System.currentTimeMillis() - start < timeoutMillis) {
+                    try {
+                        Thread.sleep(100);
+                    } catch (InterruptedException ignored) {
+                        throw new RuntimeException(e);
+                    }
+                } else {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+
     protected int getCurrentUserId() throws Exception {
         setCurrentUserId();
 
         return mCurrentUserId;
     }
 
+    protected boolean isSuccessful(CommandResult result) {
+        if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
+            return false;
+        }
+        String stdout = result.getStdout();
+        if (stdout.contains(ERROR_MESSAGE_TAG)) {
+            return false;
+        }
+        String stderr = result.getStderr();
+        return (stderr == null || stderr.trim().isEmpty());
+    }
+
     private void setCurrentUserId() throws Exception {
         if (mCurrentUserId != NativeDevice.INVALID_USER_ID) return;
 
@@ -41,4 +94,11 @@
         mCurrentUserId = device.getCurrentUser();
         CLog.i("Current user: %d");
     }
+
+    protected interface ThrowingRunnable {
+        /**
+         * Similar to {@link Runnable#run} but has {@code throws Exception}.
+         */
+        void run() throws Exception;
+    }
 }
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java b/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
index 4092360..b82cc48 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
@@ -143,6 +143,11 @@
                 + sContext.getOpPackageName(), output -> output.contains("Enabled"));
     }
 
+    private static void disableChange() {
+        SystemUtil.runShellCommand("am compat disable --no-kill REQUIRE_EXACT_ALARM_PERMISSION "
+                + sContext.getOpPackageName(), output -> output.contains("Disabled"));
+    }
+
     @After
     public void resetChanges() {
         // This is needed because compat persists the overrides beyond package uninstall
@@ -228,6 +233,13 @@
         assertTrue(mAlarmManager.canScheduleExactAlarms());
     }
 
+    @Test
+    public void canScheduleExactAlarmWhenChangeDisabled() throws IOException {
+        disableChange();
+        revokeAppOp();
+        assertTrue(mAlarmManager.canScheduleExactAlarms());
+    }
+
     @Test(expected = SecurityException.class)
     public void setAlarmClockWithoutPermission() throws IOException {
         revokeAppOp();
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
index 816385b..85715be 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
@@ -193,6 +193,10 @@
             // TODO(b/159176758): make sure that initial power supply is on.
             BatteryUtils.runDumpsysBatterySetPluggedIn(true);
         }
+
+        // Kill as many things in the background as possible so we avoid LMK interfering with the
+        // test.
+        mUiDevice.executeShellCommand("am kill-all");
     }
 
     @Test
diff --git a/tests/app/src/android/app/cts/UiModeManagerTest.java b/tests/app/src/android/app/cts/UiModeManagerTest.java
index eaa16d9..979df70 100644
--- a/tests/app/src/android/app/cts/UiModeManagerTest.java
+++ b/tests/app/src/android/app/cts/UiModeManagerTest.java
@@ -28,6 +28,7 @@
 import android.content.res.Configuration;
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
+import android.platform.test.annotations.SystemUserOnly;
 import android.test.AndroidTestCase;
 import android.util.ArraySet;
 import android.util.Log;
@@ -48,6 +49,9 @@
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
+
+@SystemUserOnly(reason = "UiAutomation doesn't support untrusted UID's. "
+        + "see UiAutomationConnection#throwIfCalledByNotTrustedUidLocked")
 public class UiModeManagerTest extends AndroidTestCase {
     private static final String TAG = "UiModeManagerTest";
     private static final long MAX_WAIT_TIME_SECS = 2;
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchBatchResultCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchBatchResultCtsTest.java
index aab7098..a1f052f 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchBatchResultCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchBatchResultCtsTest.java
@@ -18,8 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.testng.Assert.expectThrows;
-
 import android.app.appsearch.AppSearchBatchResult;
 import android.app.appsearch.AppSearchResult;
 
@@ -35,7 +33,6 @@
                         .setResult("keySuccess3", AppSearchResult.newSuccessfulResult(3))
                         .build();
         assertThat(result.isSuccess()).isTrue();
-        result.checkSuccess();
     }
 
     @Test
@@ -58,8 +55,6 @@
 
         assertThat(result1.isSuccess()).isFalse();
         assertThat(result2.isSuccess()).isFalse();
-        expectThrows(IllegalStateException.class, result1::checkSuccess);
-        expectThrows(IllegalStateException.class, result2::checkSuccess);
     }
 
     @Test
@@ -77,9 +72,7 @@
                         .build();
 
         assertThat(result1.isSuccess()).isFalse();
-        expectThrows(IllegalStateException.class, result1::checkSuccess);
         assertThat(result2.isSuccess()).isTrue();
-        result2.checkSuccess();
     }
 
     @Test
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java
index bc7f271..fa5c127 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java
@@ -18,12 +18,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.testng.Assert.expectThrows;
+import static org.junit.Assert.assertThrows;
 
 import android.app.appsearch.AppSearchSchema;
 import android.app.appsearch.AppSearchSchema.PropertyConfig;
 import android.app.appsearch.AppSearchSchema.StringPropertyConfig;
-import android.app.appsearch.exceptions.IllegalSchemaException;
 
 import com.android.server.appsearch.testing.AppSearchEmail;
 
@@ -35,7 +34,7 @@
     @Test
     public void testInvalidEnums() {
         StringPropertyConfig.Builder builder = new StringPropertyConfig.Builder("test");
-        expectThrows(IllegalArgumentException.class, () -> builder.setCardinality(99));
+        assertThrows(IllegalArgumentException.class, () -> builder.setCardinality(99));
     }
 
     @Test
@@ -57,9 +56,9 @@
                                                 StringPropertyConfig.INDEXING_TYPE_PREFIXES)
                                         .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
                                         .build());
-        IllegalSchemaException e =
-                expectThrows(
-                        IllegalSchemaException.class,
+        IllegalArgumentException e =
+                assertThrows(
+                        IllegalArgumentException.class,
                         () ->
                                 builder.addProperty(
                                         new StringPropertyConfig.Builder("subject")
@@ -278,10 +277,10 @@
 
         // Setting an indexing type other NONE with the default tokenizer type (NONE) should fail.
         builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS);
-        expectThrows(IllegalStateException.class, () -> builder.build());
+        assertThrows(IllegalStateException.class, () -> builder.build());
 
         builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_PREFIXES);
-        expectThrows(IllegalStateException.class, () -> builder.build());
+        assertThrows(IllegalStateException.class, () -> builder.build());
 
         // Explicitly setting the default should work fine.
         builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_NONE);
@@ -290,10 +289,10 @@
         // Explicitly setting the default tokenizer type should result in the same behavior.
         builder.setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_NONE)
                 .setIndexingType(StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS);
-        expectThrows(IllegalStateException.class, () -> builder.build());
+        assertThrows(IllegalStateException.class, () -> builder.build());
 
         builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_PREFIXES);
-        expectThrows(IllegalStateException.class, () -> builder.build());
+        assertThrows(IllegalStateException.class, () -> builder.build());
 
         builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_NONE);
         assertThat(builder.build()).isNotNull();
@@ -306,10 +305,10 @@
         final StringPropertyConfig.Builder builder =
                 new StringPropertyConfig.Builder("property")
                         .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN);
-        expectThrows(IllegalStateException.class, () -> builder.build());
+        assertThrows(IllegalStateException.class, () -> builder.build());
 
         builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_NONE);
-        expectThrows(IllegalStateException.class, () -> builder.build());
+        assertThrows(IllegalStateException.class, () -> builder.build());
 
         // Setting indexing type to be something other than NONE with tokenizer type PLAIN should
         // be just fine.
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaMigrationCtsTestBase.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaMigrationCtsTestBase.java
index 830cc25..a87a1ac 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaMigrationCtsTestBase.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaMigrationCtsTestBase.java
@@ -24,7 +24,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.testng.Assert.expectThrows;
+import static org.junit.Assert.assertThrows;
 
 import android.annotation.NonNull;
 import android.app.appsearch.AppSearchBatchResult;
@@ -72,7 +72,6 @@
  * FALSE  FALSE   FALSE   TRUE    Impossible case, migrators are inactivity
  * FALSE  FALSE   FALSE   FALSE                             fail             throw error
  */
-// TODO(b/178060626) add a platform version of this test
 public abstract class AppSearchSchemaMigrationCtsTestBase {
 
     private static final String DB_NAME = "";
@@ -359,7 +358,7 @@
         AppSearchSchema $B_C_Schema = new AppSearchSchema.Builder("testSchema").build();
 
         ExecutionException exception =
-                expectThrows(
+                assertThrows(
                         ExecutionException.class,
                         () ->
                                 mDb.setSchema(
@@ -380,7 +379,7 @@
         AppSearchSchema $B_$C_Schema = new AppSearchSchema.Builder("testSchema").build();
 
         ExecutionException exception =
-                expectThrows(
+                assertThrows(
                         ExecutionException.class,
                         () ->
                                 mDb.setSchema(
@@ -772,7 +771,7 @@
 
         // SetSchema with forceOverride=false
         ExecutionException exception =
-                expectThrows(
+                assertThrows(
                         ExecutionException.class,
                         () ->
                                 mDb.setSchema(
@@ -900,7 +899,7 @@
 
         // SetSchema with forceOverride=false
         ExecutionException exception =
-                expectThrows(
+                assertThrows(
                         ExecutionException.class,
                         () ->
                                 mDb.setSchema(
@@ -969,11 +968,15 @@
         // SetSchema with forceOverride=false
         // Source type exist, destination type doesn't exist.
         ExecutionException exception =
-                expectThrows(
+                assertThrows(
                         ExecutionException.class,
                         () ->
                                 mDb.setSchema(
                                                 new SetSchemaRequest.Builder()
+                                                        .addSchemas(
+                                                                new AppSearchSchema.Builder(
+                                                                                "emptySchema")
+                                                                        .build())
                                                         .setMigrator(
                                                                 "sourceSchema",
                                                                 migrator_sourceToNowhere)
@@ -989,11 +992,15 @@
         // SetSchema with forceOverride=true
         // Source type exist, destination type doesn't exist.
         exception =
-                expectThrows(
+                assertThrows(
                         ExecutionException.class,
                         () ->
                                 mDb.setSchema(
                                                 new SetSchemaRequest.Builder()
+                                                        .addSchemas(
+                                                                new AppSearchSchema.Builder(
+                                                                                "emptySchema")
+                                                                        .build())
                                                         .setMigrator(
                                                                 "sourceSchema",
                                                                 migrator_sourceToNowhere)
@@ -1053,6 +1060,8 @@
                 mDb.setSchema(
                                 new SetSchemaRequest.Builder()
                                         .addSchemas(destinationSchema)
+                                        .addSchemas(
+                                                new AppSearchSchema.Builder("emptySchema").build())
                                         .setMigrator(
                                                 "nonExistSchema", migrator_nowhereToDestination)
                                         .setVersion(2) //  upgrade version
@@ -1065,6 +1074,8 @@
                 mDb.setSchema(
                                 new SetSchemaRequest.Builder()
                                         .addSchemas(destinationSchema)
+                                        .addSchemas(
+                                                new AppSearchSchema.Builder("emptySchema").build())
                                         .setMigrator(
                                                 "nonExistSchema", migrator_nowhereToDestination)
                                         .setVersion(2) //  upgrade version
@@ -1110,6 +1121,8 @@
         SetSchemaResponse setSchemaResponse =
                 mDb.setSchema(
                                 new SetSchemaRequest.Builder()
+                                        .addSchemas(
+                                                new AppSearchSchema.Builder("emptySchema").build())
                                         .setMigrator("nonExistSchema", migrator_nowhereToNowhere)
                                         .setVersion(2) //  upgrade version
                                         .build())
@@ -1120,6 +1133,8 @@
         setSchemaResponse =
                 mDb.setSchema(
                                 new SetSchemaRequest.Builder()
+                                        .addSchemas(
+                                                new AppSearchSchema.Builder("emptySchema").build())
                                         .setMigrator("nonExistSchema", migrator_nowhereToNowhere)
                                         .setVersion(2) //  upgrade version
                                         .setForceOverride(true)
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSessionCtsTestBase.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSessionCtsTestBase.java
index cfda19f..d30d661 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSessionCtsTestBase.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSessionCtsTestBase.java
@@ -26,7 +26,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.testng.Assert.expectThrows;
+import static org.junit.Assert.assertThrows;
 
 import android.annotation.NonNull;
 import android.app.appsearch.AppSearchBatchResult;
@@ -135,7 +135,7 @@
                 new AppSearchSchema.Builder(AppSearchEmail.SCHEMA_TYPE).build();
 
         Throwable throwable =
-                expectThrows(
+                assertThrows(
                                 ExecutionException.class,
                                 () ->
                                         mDb1.setSchema(
@@ -151,7 +151,7 @@
         assertThat(exception).hasMessageThat().contains("Incompatible types: {builtin:Email}");
 
         throwable =
-                expectThrows(
+                assertThrows(
                                 ExecutionException.class,
                                 () -> mDb1.setSchema(new SetSchemaRequest.Builder().build()).get())
                         .getCause();
@@ -546,7 +546,7 @@
 
         // Try to remove the email schema. This should fail as it's an incompatible change.
         Throwable failResult1 =
-                expectThrows(
+                assertThrows(
                                 ExecutionException.class,
                                 () -> mDb1.setSchema(new SetSchemaRequest.Builder().build()).get())
                         .getCause();
@@ -628,7 +628,7 @@
         // Try to remove the email schema in database1. This should fail as it's an incompatible
         // change.
         Throwable failResult1 =
-                expectThrows(
+                assertThrows(
                                 ExecutionException.class,
                                 () -> mDb1.setSchema(new SetSchemaRequest.Builder().build()).get())
                         .getCause();
@@ -2070,6 +2070,93 @@
     }
 
     @Test
+    public void testSetSnippetCount() throws Exception {
+        // Schema registration
+        AppSearchSchema genericSchema =
+                new AppSearchSchema.Builder("Generic")
+                        .addProperty(
+                                new StringPropertyConfig.Builder("subject")
+                                        .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
+                                        .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+                                        .setIndexingType(
+                                                StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+                                        .build())
+                        .build();
+        mDb1.setSchema(new SetSchemaRequest.Builder().addSchemas(genericSchema).build()).get();
+
+        // Index documents
+        checkIsBatchResultSuccess(
+                mDb1.put(
+                        new PutDocumentsRequest.Builder()
+                                .addGenericDocuments(
+                                        new GenericDocument.Builder<>("namespace", "id1", "Generic")
+                                                .setPropertyString(
+                                                        "subject",
+                                                        "I like cats",
+                                                        "I like dogs",
+                                                        "I like birds",
+                                                        "I like fish")
+                                                .setScore(10)
+                                                .build(),
+                                        new GenericDocument.Builder<>("namespace", "id2", "Generic")
+                                                .setPropertyString(
+                                                        "subject",
+                                                        "I like red",
+                                                        "I like green",
+                                                        "I like blue",
+                                                        "I like yellow")
+                                                .setScore(20)
+                                                .build(),
+                                        new GenericDocument.Builder<>("namespace", "id3", "Generic")
+                                                .setPropertyString(
+                                                        "subject",
+                                                        "I like cupcakes",
+                                                        "I like donuts",
+                                                        "I like eclairs",
+                                                        "I like froyo")
+                                                .setScore(5)
+                                                .build())
+                                .build()));
+
+        // Query for the document
+        SearchResultsShim searchResults =
+                mDb1.search(
+                        "like",
+                        new SearchSpec.Builder()
+                                .addFilterSchemas("Generic")
+                                .setSnippetCount(2)
+                                .setSnippetCountPerProperty(3)
+                                .setMaxSnippetSize(11)
+                                .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE)
+                                .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+                                .build());
+
+        // Check result 1
+        List<SearchResult> results = searchResults.getNextPage().get();
+        assertThat(results).hasSize(3);
+
+        assertThat(results.get(0).getGenericDocument().getId()).isEqualTo("id2");
+        List<SearchResult.MatchInfo> matchInfos = results.get(0).getMatchInfos();
+        assertThat(matchInfos).hasSize(3);
+        assertThat(matchInfos.get(0).getSnippet()).isEqualTo("I like red");
+        assertThat(matchInfos.get(1).getSnippet()).isEqualTo("I like");
+        assertThat(matchInfos.get(2).getSnippet()).isEqualTo("I like blue");
+
+        // Check result 2
+        assertThat(results.get(1).getGenericDocument().getId()).isEqualTo("id1");
+        matchInfos = results.get(1).getMatchInfos();
+        assertThat(matchInfos).hasSize(3);
+        assertThat(matchInfos.get(0).getSnippet()).isEqualTo("I like cats");
+        assertThat(matchInfos.get(1).getSnippet()).isEqualTo("I like dogs");
+        assertThat(matchInfos.get(2).getSnippet()).isEqualTo("I like");
+
+        // Check result 2
+        assertThat(results.get(2).getGenericDocument().getId()).isEqualTo("id3");
+        matchInfos = results.get(2).getMatchInfos();
+        assertThat(matchInfos).isEmpty();
+    }
+
+    @Test
     public void testCJKSnippet() throws Exception {
         // Schema registration
         AppSearchSchema genericSchema =
@@ -2929,7 +3016,7 @@
             // Try to query the closed database
             // We are using the same-thread db here to make sure it has been closed.
             IllegalStateException e =
-                    expectThrows(
+                    assertThrows(
                             IllegalStateException.class,
                             () ->
                                     sameThreadDb.search(
@@ -3036,7 +3123,7 @@
 
         // Use an incorrect namespace; it fails
         ExecutionException e =
-                expectThrows(
+                assertThrows(
                         ExecutionException.class,
                         () ->
                                 mDb1.reportUsage(
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java
index 649448a..70f9b48 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java
@@ -18,7 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.testng.Assert.expectThrows;
+import static org.junit.Assert.assertThrows;
 
 import android.app.appsearch.GenericDocument;
 
@@ -343,62 +343,12 @@
                 new GenericDocument.Builder<>("namespace", "id1", "schemaType1");
         String nullString = null;
 
-        expectThrows(
+        assertThrows(
                 IllegalArgumentException.class,
                 () -> builder.setPropertyString("testKey", "string1", nullString));
     }
 
     @Test
-    public void testDocument_toBuilder() {
-        GenericDocument document1 =
-                new GenericDocument.Builder<>(/*namespace=*/ "", "id1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setPropertyLong("longKey1", 1L, 2L, 3L)
-                        .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
-                        .setPropertyBoolean("booleanKey1", true, false, true)
-                        .setPropertyString("stringKey1", "String1", "String2", "String3")
-                        .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
-                        .setPropertyDocument(
-                                "documentKey1", sDocumentProperties1, sDocumentProperties2)
-                        .build();
-        GenericDocument document2 =
-                document1.toBuilder()
-                        .setId("id2")
-                        .setNamespace("namespace2")
-                        .setPropertyBytes("byteKey1", sByteArray2)
-                        .setPropertyLong("longKey2", 10L)
-                        .clearProperty("booleanKey1")
-                        .build();
-
-        // Make sure old doc hasn't changed
-        assertThat(document1.getId()).isEqualTo("id1");
-        assertThat(document1.getNamespace()).isEqualTo("");
-        assertThat(document1.getPropertyLongArray("longKey1"))
-                .asList()
-                .containsExactly(1L, 2L, 3L)
-                .inOrder();
-        assertThat(document1.getPropertyBooleanArray("booleanKey1"))
-                .asList()
-                .containsExactly(true, false, true)
-                .inOrder();
-        assertThat(document1.getPropertyLongArray("longKey2")).isNull();
-
-        // Make sure the new doc contains the expected values
-        GenericDocument expectedDoc =
-                new GenericDocument.Builder<>("namespace2", "id2", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setPropertyLong("longKey1", 1L, 2L, 3L)
-                        .setPropertyLong("longKey2", 10L)
-                        .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
-                        .setPropertyString("stringKey1", "String1", "String2", "String3")
-                        .setPropertyBytes("byteKey1", sByteArray2)
-                        .setPropertyDocument(
-                                "documentKey1", sDocumentProperties1, sDocumentProperties2)
-                        .build();
-        assertThat(document2).isEqualTo(expectedDoc);
-    }
-
-    @Test
     public void testRetrieveTopLevelProperties() {
         GenericDocument doc =
                 new GenericDocument.Builder<>("namespace", "id1", "schema1")
@@ -689,19 +639,19 @@
 
         // Some paths are invalid because they are malformed. These throw an exception --- the
         // querier shouldn't provide such paths.
-        expectThrows(
+        assertThrows(
                 IllegalArgumentException.class,
                 () -> doc.getPropertyStringArray("propDocs.[0]propInts"));
-        expectThrows(
+        assertThrows(
                 IllegalArgumentException.class, () -> doc.getPropertyStringArray("propString[0"));
-        expectThrows(
+        assertThrows(
                 IllegalArgumentException.class, () -> doc.getPropertyStringArray("propString[0.]"));
-        expectThrows(
+        assertThrows(
                 IllegalArgumentException.class,
                 () -> doc.getPropertyStringArray("propString[banana]"));
-        expectThrows(
+        assertThrows(
                 IllegalArgumentException.class, () -> doc.getPropertyStringArray("propString[-1]"));
-        expectThrows(
+        assertThrows(
                 IllegalArgumentException.class, () -> doc.getPropertyStringArray("propDocs[0]cat"));
     }
 
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/GetSchemaResponseCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/GetSchemaResponseCtsTest.java
new file mode 100644
index 0000000..d3ffa0a
--- /dev/null
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/GetSchemaResponseCtsTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.appsearch.cts.app;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.appsearch.AppSearchSchema;
+import android.app.appsearch.GetSchemaResponse;
+
+import org.junit.Test;
+
+public class GetSchemaResponseCtsTest {
+    @Test
+    public void testRebuild() {
+        AppSearchSchema schema1 =
+                new AppSearchSchema.Builder("Email1")
+                        .addProperty(
+                                new AppSearchSchema.StringPropertyConfig.Builder("subject")
+                                        .setCardinality(
+                                                AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .setIndexingType(
+                                                AppSearchSchema.StringPropertyConfig
+                                                        .INDEXING_TYPE_PREFIXES)
+                                        .setTokenizerType(
+                                                AppSearchSchema.StringPropertyConfig
+                                                        .TOKENIZER_TYPE_PLAIN)
+                                        .build())
+                        .build();
+        AppSearchSchema schema2 =
+                new AppSearchSchema.Builder("Email2")
+                        .addProperty(
+                                new AppSearchSchema.StringPropertyConfig.Builder("subject")
+                                        .setCardinality(
+                                                AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .setIndexingType(
+                                                AppSearchSchema.StringPropertyConfig
+                                                        .INDEXING_TYPE_PREFIXES)
+                                        .setTokenizerType(
+                                                AppSearchSchema.StringPropertyConfig
+                                                        .TOKENIZER_TYPE_PLAIN)
+                                        .build())
+                        .build();
+
+        GetSchemaResponse.Builder builder =
+                new GetSchemaResponse.Builder().setVersion(42).addSchema(schema1);
+
+        GetSchemaResponse original = builder.build();
+        GetSchemaResponse rebuild = builder.setVersion(37).addSchema(schema2).build();
+
+        // rebuild won't effect the original object
+        assertThat(original.getVersion()).isEqualTo(42);
+        assertThat(original.getSchemas()).containsExactly(schema1);
+
+        assertThat(rebuild.getVersion()).isEqualTo(37);
+        assertThat(rebuild.getSchemas()).containsExactly(schema1, schema2);
+    }
+}
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
index f9271b8..7dbe8d9 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
@@ -21,7 +21,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.testng.Assert.expectThrows;
+import static org.junit.Assert.assertThrows;
 
 import android.annotation.NonNull;
 import android.app.appsearch.AppSearchResult;
@@ -744,7 +744,7 @@
         SearchResult firstResult = page.get(0);
 
         ExecutionException exception =
-                expectThrows(
+                assertThrows(
                         ExecutionException.class,
                         () ->
                                 mGlobalAppSearchManager
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/PutDocumentsRequestCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/PutDocumentsRequestCtsTest.java
new file mode 100644
index 0000000..b42d4a6
--- /dev/null
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/PutDocumentsRequestCtsTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.app.appsearch.cts.app;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.appsearch.PutDocumentsRequest;
+
+import com.android.server.appsearch.testing.AppSearchEmail;
+
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Test;
+
+import java.util.Set;
+
+public class PutDocumentsRequestCtsTest {
+
+    @Test
+    public void addGenericDocument_byCollection() {
+        Set<AppSearchEmail> emails =
+                ImmutableSet.of(
+                        new AppSearchEmail.Builder("namespace", "test1").build(),
+                        new AppSearchEmail.Builder("namespace", "test2").build());
+        PutDocumentsRequest request =
+                new PutDocumentsRequest.Builder().addGenericDocuments(emails).build();
+
+        assertThat(request.getGenericDocuments().get(0).getId()).isEqualTo("test1");
+        assertThat(request.getGenericDocuments().get(1).getId()).isEqualTo("test2");
+    }
+}
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/SetSchemaRequestCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/SetSchemaRequestCtsTest.java
index bf5a44a..9ae7e60 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/SetSchemaRequestCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/SetSchemaRequestCtsTest.java
@@ -19,7 +19,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.testng.Assert.expectThrows;
+import static org.junit.Assert.assertThrows;
 
 import android.annotation.NonNull;
 import android.app.appsearch.AppSearchSchema;
@@ -189,7 +189,7 @@
     @Test
     public void testInvalidSchemaReferences_fromDisplayedBySystem() {
         IllegalArgumentException expected =
-                expectThrows(
+                assertThrows(
                         IllegalArgumentException.class,
                         () ->
                                 new SetSchemaRequest.Builder()
@@ -201,7 +201,7 @@
     @Test
     public void testInvalidSchemaReferences_fromPackageVisibility() {
         IllegalArgumentException expected =
-                expectThrows(
+                assertThrows(
                         IllegalArgumentException.class,
                         () ->
                                 new SetSchemaRequest.Builder()
@@ -328,7 +328,7 @@
     @Test
     public void testSetVersion() {
         IllegalArgumentException exception =
-                expectThrows(
+                assertThrows(
                         IllegalArgumentException.class,
                         () ->
                                 new SetSchemaRequest.Builder()
@@ -343,4 +343,15 @@
                         .build();
         assertThat(request.getVersion()).isEqualTo(1);
     }
+
+    @Test
+    public void testSetVersion_emptyDb() {
+        IllegalArgumentException exception =
+                assertThrows(
+                        IllegalArgumentException.class,
+                        () -> new SetSchemaRequest.Builder().setVersion(135).build());
+        assertThat(exception)
+                .hasMessageThat()
+                .contains("Cannot set version to the request if schema is empty.");
+    }
 }
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index f083968..d6d5cfc 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -25,7 +25,6 @@
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraCharacteristics.Key;
 import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraExtensionCharacteristics;
 import android.hardware.camera2.CameraManager;
 import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CaptureRequest;
@@ -107,8 +106,9 @@
     private static final long PREVIEW_RUN_MS = 500;
     private static final long FRAME_DURATION_30FPS_NSEC = (long) 1e9 / 30;
 
-    private static final long MIN_BACK_SENSOR_PERFORMANCE_CLASS_RESOLUTION = 12000000;
-    private static final long MIN_FRONT_SENSOR_PERFORMANCE_CLASS_RESOLUTION = 6000000;
+    private static final long MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION = 12000000;
+    private static final long MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION = 5000000;
+    private static final long MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION = 4000000;
 
     /*
      * HW Levels short hand
@@ -2551,19 +2551,20 @@
     }
 
     /**
-     * Check camera characteristics for S Performance class requirements as specified
+     * Check camera characteristics for R and S Performance class requirements as specified
      * in CDD camera section 7.5
      */
     @Test
     @CddTest(requirement="7.5")
-    public void testCameraSPerfClassCharacteristics() throws Exception {
+    public void testCameraPerfClassCharacteristics() throws Exception {
         if (mAdoptShellPerm) {
             // Skip test for system camera. Performance class is only applicable for public camera
             // ids.
             return;
         }
+        boolean isRPerfClass = CameraTestUtils.isRPerfClass();
         boolean isSPerfClass = CameraTestUtils.isSPerfClass();
-        if (!isSPerfClass) {
+        if (!isRPerfClass && !isSPerfClass) {
             return;
         }
 
@@ -2595,36 +2596,9 @@
             if (isPrimaryRear) {
                 hasPrimaryRear = true;
                 mCollector.expectTrue("Primary rear camera resolution should be at least " +
-                        MIN_BACK_SENSOR_PERFORMANCE_CLASS_RESOLUTION + " pixels, is "+
+                        MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION + " pixels, is "+
                         sensorResolution,
-                        sensorResolution >= MIN_BACK_SENSOR_PERFORMANCE_CLASS_RESOLUTION);
-
-                // 720P @ 240fps
-                boolean supportHighSpeed = staticInfo.isCapabilitySupported(CONSTRAINED_HIGH_SPEED);
-                mCollector.expectTrue("Primary rear camera should support high speed recording",
-                        supportHighSpeed);
-                if (supportHighSpeed) {
-                    boolean supportHD240 = false;
-                    Size[] availableHighSpeedSizes = config.getHighSpeedVideoSizes();
-                    for (Size size : availableHighSpeedSizes) {
-                        if (!size.equals(HD)) {
-                            continue;
-                        }
-                        Range<Integer>[] availableFpsRanges =
-                                config.getHighSpeedVideoFpsRangesFor(size);
-                        for (Range<Integer> fpsRange : availableFpsRanges) {
-                            if (fpsRange.getUpper() == 240) {
-                                supportHD240 = true;
-                                break;
-                            }
-                        }
-                        if (supportHD240) {
-                            break;
-                        }
-                    }
-                    mCollector.expectTrue("Primary rear camera should support HD @ 240fps",
-                            supportHD240);
-                }
+                        sensorResolution >= MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION);
 
                 // 4K @ 30fps
                 boolean supportUHD = videoSizes.contains(UHD);
@@ -2639,10 +2613,17 @@
                 }
             } else {
                 hasPrimaryFront = true;
-                mCollector.expectTrue("Primary front camera resolution should be at least " +
-                        MIN_FRONT_SENSOR_PERFORMANCE_CLASS_RESOLUTION + " pixels, is "+
-                        sensorResolution,
-                        sensorResolution >= MIN_FRONT_SENSOR_PERFORMANCE_CLASS_RESOLUTION);
+                if (isSPerfClass) {
+                    mCollector.expectTrue("Primary front camera resolution should be at least " +
+                            MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION + " pixels, is "+
+                            sensorResolution,
+                            sensorResolution >= MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION);
+                } else {
+                    mCollector.expectTrue("Primary front camera resolution should be at least " +
+                            MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION + " pixels, is "+
+                            sensorResolution,
+                            sensorResolution >= MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION);
+                }
                 // 1080P @ 30fps
                 boolean supportFULLHD = videoSizes.contains(FULLHD);
                 mCollector.expectTrue("Primary front camera should support 1080P video recording",
@@ -2657,37 +2638,34 @@
 
             String facingString = hasPrimaryRear ? "rear" : "front";
             // H-1-3
-            mCollector.expectTrue("Primary " + facingString + " camera should be at least FULL, " +
-                   "but is " + toStringHardwareLevel(staticInfo.getHardwareLevelChecked()),
-                   staticInfo.isHardwareLevelAtLeastFull());
-
-            // H-1-4
-            if (isPrimaryRear) {
-                mCollector.expectTrue("Primary rear camera should support RAW capability",
-                        staticInfo.isCapabilitySupported(RAW));
+            if (isSPerfClass || (isRPerfClass && isPrimaryRear)) {
+                mCollector.expectTrue("Primary " + facingString +
+                        " camera should be at least FULL, but is " +
+                        toStringHardwareLevel(staticInfo.getHardwareLevelChecked()),
+                        staticInfo.isHardwareLevelAtLeastFull());
+            } else {
+                mCollector.expectTrue("Primary " + facingString +
+                        " camera should be at least LIMITED, but is " +
+                        toStringHardwareLevel(staticInfo.getHardwareLevelChecked()),
+                        staticInfo.isHardwareLevelAtLeastLimited());
             }
 
-            // H-1-5
+            // H-1-4
             Integer timestampSource = c.get(CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE);
             mCollector.expectTrue(
                     "Primary " + facingString + " camera should support real-time timestamp source",
                     timestampSource != null &&
                     timestampSource.equals(CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME));
 
-            // H-1-9
-            CameraExtensionCharacteristics extensionChars =
-                    mCameraManager.getCameraExtensionCharacteristics(cameraId);
-            List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
-            mCollector.expectTrue(
-                    "Primary " + facingString + " camera must support the HDR camera2 extension",
-                    supportedExtensions.contains(CameraExtensionCharacteristics.EXTENSION_HDR));
-            mCollector.expectTrue(
-                    "Primary " + facingString + " camera must support the NIGHT camera2 extension",
-                    supportedExtensions.contains(CameraExtensionCharacteristics.EXTENSION_NIGHT));
+            // H-1-8
+            if (isSPerfClass && isPrimaryRear) {
+                mCollector.expectTrue("Primary rear camera should support RAW capability",
+                        staticInfo.isCapabilitySupported(RAW));
+            }
         }
-        mCollector.expectTrue("There must be a primary rear camera for S performance class.",
+        mCollector.expectTrue("There must be a primary rear camera for performance class.",
                 hasPrimaryRear);
-        mCollector.expectTrue("There must be a primary front camera for S performance class.",
+        mCollector.expectTrue("There must be a primary front camera for performance class.",
                 hasPrimaryFront);
     }
 
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
index f495c67..1daa3f6 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -3508,9 +3508,17 @@
         return zoomRatios;
     }
 
+    private static final int PERFORMANCE_CLASS_R = Build.VERSION_CODES.R;
     private static final int PERFORMANCE_CLASS_S = Build.VERSION_CODES.R + 1;
 
     /**
+     * Check whether this mobile device is R performance class as defined in CDD
+     */
+    public static boolean isRPerfClass() {
+        return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_R;
+    }
+
+    /**
      * Check whether this mobile device is S performance class as defined in CDD
      */
     public static boolean isSPerfClass() {
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java
index 5744a04..6940ea6 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java
@@ -59,6 +59,8 @@
 import android.view.contentcapture.DataRemovalRequest;
 import android.view.contentcapture.DataRemovalRequest.LocusIdRequest;
 import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -546,7 +548,7 @@
 
         assertRightActivity(session, sessionId, activity);
 
-        final int additionalEvents = 5;
+        final int additionalEvents = 4;
         final List<ContentCaptureEvent> events = activity.assertInitialViewsAppeared(session,
                 additionalEvents);
 
@@ -605,6 +607,58 @@
         activity.assertInitialViewsDisappeared(events, additionalEvents);
     }
 
+    @Test
+    public void testComposingSpan_eventsForSpanChanges() throws Exception {
+        final CtsContentCaptureService service = enableService();
+        final ActivityWatcher watcher = startWatcher();
+
+        LoginActivity.onRootView((activity, rootView) -> ((LoginActivity) activity).mUsername
+                .setText(""));
+
+        final LoginActivity activity = launchActivity();
+        watcher.waitFor(RESUMED);
+
+        activity.syncRunOnUiThread(() -> {
+            activity.mUsername.setText("Android");
+            final InputConnection inputConnection =
+                    activity.mUsername.onCreateInputConnection(new EditorInfo());
+
+            // These 2 should be merged.
+            inputConnection.setComposingRegion(1, 2);
+            inputConnection.setComposingRegion(1, 3);
+
+            inputConnection.finishComposingText();
+            activity.mUsername.setText("end");
+            // TODO: Test setComposingText.
+        });
+
+        activity.finish();
+        watcher.waitFor(DESTROYED);
+
+        final Session session = service.getOnlyFinishedSession();
+        final ContentCaptureSessionId sessionId = session.id;
+
+        assertRightActivity(session, sessionId, activity);
+
+        final int additionalEvents = 5;
+        final List<ContentCaptureEvent> events = activity.assertInitialViewsAppeared(session,
+                additionalEvents);
+
+        final int i = LoginActivity.MIN_EVENTS;
+
+        // TODO: The first two events should probably be merged.
+        assertViewTextChanged(events, i, activity.mUsername.getAutofillId(), "Android");
+        assertNoComposingSpan(events.get(i).getText());
+        assertViewTextChanged(events, i + 1, activity.mUsername.getAutofillId(), "Android");
+        assertComposingSpan(events.get(i + 1).getText(), 1, 3);
+        assertViewTextChanged(events, i + 2, activity.mUsername.getAutofillId(), "Android");
+        assertNoComposingSpan(events.get(i + 2).getText());
+        assertViewTextChanged(events, i + 3, activity.mUsername.getAutofillId(), "end");
+        assertNoComposingSpan(events.get(i + 3).getText());
+
+        activity.assertInitialViewsDisappeared(events, additionalEvents);
+    }
+
     private void appendText(EditText editText, String text) {
         appendText(editText, text, true);
     }
diff --git a/tests/devicepolicy/Android.bp b/tests/devicepolicy/Android.bp
index 6c90226..2c7fbe9 100644
--- a/tests/devicepolicy/Android.bp
+++ b/tests/devicepolicy/Android.bp
@@ -22,6 +22,7 @@
     static_libs: [
         "compatibility-device-util-axt",
         "ctstestrunner-axt",
+        "cts-net-utils",
         "truth-prebuilt",
         "androidx.test.ext.junit",
         "testng", // used for assertThrows
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/PreferentialNetworkServiceTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/PreferentialNetworkServiceTest.java
new file mode 100644
index 0000000..5c935bf
--- /dev/null
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/PreferentialNetworkServiceTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.devicepolicy.cts;
+
+import static android.Manifest.permission.ACCESS_NETWORK_STATE;
+import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkProvider;
+import android.net.NetworkScore;
+import android.os.HandlerExecutor;
+import android.os.HandlerThread;
+import android.os.Process;
+import android.util.Range;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.EnsureHasPermission;
+import com.android.bedstead.harrier.annotations.Postsubmit;
+import com.android.bedstead.harrier.annotations.enterprise.PositivePolicyTest;
+import com.android.bedstead.harrier.policies.PreferentialNetworkService;
+import com.android.bedstead.nene.TestApis;
+import com.android.testutils.TestableNetworkCallback;
+import com.android.testutils.TestableNetworkOfferCallback;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Objects;
+import java.util.Set;
+
+// TODO(b/190797743): Move this test to to net test folder.
+@RunWith(BedsteadJUnit4.class)
+public class PreferentialNetworkServiceTest {
+    @ClassRule @Rule
+    public static final DeviceState sDeviceState = new DeviceState();
+
+    private final long DEFAULT_TIMEOUT_MS = 30_000L;
+    private final long NO_CALLBACK_TIMEOUT_MS = 100L;
+    private final String TAG = PreferentialNetworkServiceTest.class.getSimpleName();
+
+    private static final TestApis sTestApis = new TestApis();
+    private static final Context sContext = sTestApis.context().instrumentedContext();
+    private static final ConnectivityManager sCm =
+            sContext.getSystemService(ConnectivityManager.class);
+    private final HandlerThread mHandlerThread = new HandlerThread(TAG + " handler thread");
+    private final NetworkCapabilities mEnterpriseNcFilter = new NetworkCapabilities.Builder()
+            .addCapability(NET_CAPABILITY_INTERNET)
+            .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
+            .addCapability(NET_CAPABILITY_ENTERPRISE)
+            .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
+            // Only accept requests from this uid, otherwise the provider who uses this
+            // filter might see all requests of the same user if the feature is enabled.
+            .setUids(Set.of(new Range(Process.myUid(), Process.myUid())))
+            .build();
+
+    @Before
+    public void setUp() throws Exception {
+        mHandlerThread.start();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mHandlerThread.quitSafely();
+    }
+
+    /**
+     * Enable PreferentialNetworkService, verify the provider that provides enterprise slice can
+     * see the enterprise slice requests.
+     */
+    @Test
+    @Postsubmit(reason = "New test")
+    @EnsureHasPermission({ACCESS_NETWORK_STATE, NETWORK_SETTINGS})
+    @PositivePolicyTest(policy = PreferentialNetworkService.class)
+    public void setPreferentialNetworkServiceEnabled_enableService_issueRequest() {
+        // Expect a regular default network.
+        final Network defaultNetwork = Objects.requireNonNull(sCm.getActiveNetwork(),
+                "Default network is required to perform the test.");
+        final TestableNetworkCallback defaultCallback = new TestableNetworkCallback();
+        sCm.registerDefaultNetworkCallback(defaultCallback);
+        defaultCallback.expectAvailableCallbacks(defaultNetwork, /* suspended= */ false,
+                /* validated= */ true, /* blocked= */ false, DEFAULT_TIMEOUT_MS);
+
+        // Register a pair of provider and offer that can provides enterprise slice, verify it
+        // received nothing since the feature is not enabled.
+        final NetworkProvider provider =
+                new NetworkProvider(sContext, mHandlerThread.getLooper(), TAG);
+        sCm.registerNetworkProvider(provider);
+        final TestableNetworkOfferCallback offerCallback = registerEnterpriseNetworkOffer(provider);
+
+        try {
+            // Enable PreferentialNetworkService, verify the provider sees the enterprise
+            // slice request.
+            // But the network callback received nothing since it should automatically fallback to
+            // default request if there is no enterprise slice.
+            sDeviceState.dpc().devicePolicyManager().setPreferentialNetworkServiceEnabled(true);
+            offerCallback.expectOnNetworkNeeded(mEnterpriseNcFilter);
+            defaultCallback.assertNoCallback(NO_CALLBACK_TIMEOUT_MS);
+        } finally {
+            sCm.unregisterNetworkCallback(defaultCallback);
+            sDeviceState.dpc().devicePolicyManager().setPreferentialNetworkServiceEnabled(false);
+            sCm.unregisterNetworkProvider(provider);
+        }
+    }
+
+    /**
+     * Disable PreferentialNetworkService, verify the provider that provides enterprise slice cannot
+     * see the enterprise slice requests.
+     */
+    @Test
+    @Postsubmit(reason = "New test")
+    @EnsureHasPermission({ACCESS_NETWORK_STATE, NETWORK_SETTINGS})
+    @PositivePolicyTest(policy = PreferentialNetworkService.class)
+    public void setPreferentialNetworkServiceEnabled_disableService_noIssueRequest() {
+        // Expect a regular default network.
+        final Network defaultNetwork = Objects.requireNonNull(sCm.getActiveNetwork(),
+                "Default network is required to perform the test.");
+        final TestableNetworkCallback defaultCallback = new TestableNetworkCallback();
+        sCm.registerDefaultNetworkCallback(defaultCallback);
+        defaultCallback.expectAvailableCallbacks(defaultNetwork, /* suspended= */ false,
+                /* validated= */ true, /* blocked= */ false, DEFAULT_TIMEOUT_MS);
+
+        // Register a pair of provider and offer that can provides enterprise slice, verify it
+        // received nothing since the feature is not enabled.
+        final NetworkProvider provider =
+                new NetworkProvider(sContext, mHandlerThread.getLooper(), TAG);
+        sCm.registerNetworkProvider(provider);
+        final TestableNetworkOfferCallback offerCallback = registerEnterpriseNetworkOffer(provider);
+
+        try {
+            // Disable PreferentialNetworkService, verify the provider cannot see the enterprise
+            // slice request. And the network callback received nothing since there is no any
+            // change.
+            sDeviceState.dpc().devicePolicyManager().setPreferentialNetworkServiceEnabled(false);
+            offerCallback.assertNoCallback();  // Still unneeded.
+            defaultCallback.assertNoCallback(NO_CALLBACK_TIMEOUT_MS);
+        } finally {
+            sCm.unregisterNetworkCallback(defaultCallback);
+            sDeviceState.dpc().devicePolicyManager().setPreferentialNetworkServiceEnabled(false);
+            sCm.unregisterNetworkProvider(provider);
+        }
+    }
+
+    private TestableNetworkOfferCallback registerEnterpriseNetworkOffer(
+            NetworkProvider provider) {
+        final TestableNetworkOfferCallback offerCallback =
+                new TestableNetworkOfferCallback(DEFAULT_TIMEOUT_MS, NO_CALLBACK_TIMEOUT_MS);
+        provider.registerNetworkOffer(new NetworkScore.Builder().build(), mEnterpriseNcFilter,
+                new HandlerExecutor(mHandlerThread.getThreadHandler()), offerCallback);
+        offerCallback.assertNoCallback();
+        return offerCallback;
+    }
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
index 2ae9628..fd652f3 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
@@ -299,8 +299,7 @@
         // Note that we're using getBounds() in portrait, rather than getAppBounds() like other
         // tests, because we're comparing to the display size and therefore need to consider insets.
         runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY,
-                /* expectedInPortrait= */ SIZE_COMPAT_DISPLAY_ASPECT_RATIO,
-                /* expectedInLandscape= */ FIXED_ORIENTATION_MIN_ASPECT_RATIO,
+                /* expected= */ SIZE_COMPAT_DISPLAY_ASPECT_RATIO,
                 /* useAppBoundsInPortrait= */false);
     }
 
@@ -314,8 +313,7 @@
         // Note that we're using getBounds() in portrait, rather than getAppBounds() like other
         // tests, because we're comparing to the display size and therefore need to consider insets.
         runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY,
-                /* expectedInPortrait= */ SIZE_COMPAT_DISPLAY_ASPECT_RATIO,
-                /* expectedInLandscape= */ FIXED_ORIENTATION_MIN_ASPECT_RATIO,
+                /* expected= */ SIZE_COMPAT_DISPLAY_ASPECT_RATIO,
                 /* useAppBoundsInPortrait= */false);
     }
 
@@ -520,7 +518,7 @@
      * @param expected the expected aspect ratio in both portrait and landscape displays.
      */
     private void runMinAspectRatioTest(ComponentName activity, float expected) {
-        runMinAspectRatioTest(activity, expected, expected, /* useAppBoundsInPortrait= */ true);
+        runMinAspectRatioTest(activity, expected, /* useAppBoundsInPortrait= */ true);
     }
 
     /**
@@ -528,13 +526,13 @@
      * aspect ratio. The second time, the display is resized to a landscape aspect ratio.
      *
      * @param activity               the activity under test.
-     * @param expectedInPortrait     the expected aspect ratio in portrait display.
-     * @param expectedInLandscape    the expected aspect ratio in portrait display.
+     * @param expected               the expected aspect ratio in both a portrait and a landscape
+     *                               display.
      * @param useAppBoundsInPortrait whether to use {@code activity#getAppBounds} rather than
      *                               {@code activity.getBounds} in portrait display.
      */
-    private void runMinAspectRatioTest(ComponentName activity, float expectedInPortrait,
-            float expectedInLandscape, boolean useAppBoundsInPortrait) {
+    private void runMinAspectRatioTest(ComponentName activity, float expected,
+            boolean useAppBoundsInPortrait) {
         // Change the aspect ratio of the display to something that is smaller than all the aspect
         // ratios used throughout those tests but still portrait. This ensures we're using
         // enforcing aspect ratio behaviour within orientation.
@@ -543,7 +541,7 @@
         mDisplayMetricsSession.changeAspectRatio(SIZE_COMPAT_DISPLAY_ASPECT_RATIO,
                 ORIENTATION_PORTRAIT);
         launchActivity(activity);
-        assertEquals(expectedInPortrait,
+        assertEquals(expected,
                 getActivityAspectRatio(activity, /* useAppBounds= */ useAppBoundsInPortrait),
                 FLOAT_EQUALITY_DELTA);
 
@@ -552,10 +550,8 @@
         mDisplayMetricsSession.changeAspectRatio(SIZE_COMPAT_DISPLAY_ASPECT_RATIO,
                 ORIENTATION_LANDSCAPE);
         launchActivity(activity);
-        // A different aspect ratio logic is applied in fixed orientation letterboxing, so we need
-        // to use getBounds() rather than getAppBounds() here.
-        assertEquals(expectedInLandscape,
-                getActivityAspectRatio(activity, /* useAppBounds= */ false),
+        assertEquals(expected,
+                getActivityAspectRatio(activity, /* useAppBounds= */ true),
                 FLOAT_EQUALITY_DELTA);
     }
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
index 10b8b4b..01b1104 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
@@ -92,6 +92,8 @@
     private final int TOTAL_NUMBER_OF_CLICKS = 100;
     private final ActivityTestRule<TestActivity> mActivityRule =
             new ActivityTestRule<>(TestActivity.class);
+    private static final int TAPPING_TARGET_WINDOW_SIZE = 100;
+    private static final int PARTIAL_OBSCURING_WINDOW_SIZE = 30;
 
     private Instrumentation mInstrumentation;
     private final WindowManagerStateHelper mWmState = new WindowManagerStateHelper();
@@ -272,13 +274,14 @@
         intent.setComponent(Components.OVERLAY_TEST_SERVICE);
         final String windowName = "Test Overlay";
         final AtomicBoolean touchReceived = new AtomicBoolean(false);
+        final int[] viewOnScreenLocation = new int[2];
         try {
             // Set up a touchable window.
             mActivityRule.runOnUiThread(() -> {
                 mView = new View(mActivity);
                 p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
-                p.width = 100;
-                p.height = 100;
+                p.width = TAPPING_TARGET_WINDOW_SIZE;
+                p.height = TAPPING_TARGET_WINDOW_SIZE;
                 p.gravity = Gravity.CENTER;
                 mView.setFilterTouchesWhenObscured(true);
                 mView.setOnClickListener((v) -> {
@@ -289,10 +292,16 @@
                     return false;
                 });
                 mActivity.addWindow(mView, p);
-
+            });
+            mInstrumentation.waitForIdleSync();
+            mActivityRule.runOnUiThread(() -> {
+                mView.getLocationOnScreen(viewOnScreenLocation);
                 // Set up an overlap window from service, use different process.
                 WindowManager.LayoutParams params = getObscuringViewLayoutParams(windowName);
                 params.flags |= FLAG_NOT_TOUCHABLE;
+                placeWindowAtLayoutCenter(params, TAPPING_TARGET_WINDOW_SIZE,
+                        viewOnScreenLocation[0], viewOnScreenLocation[1],
+                        TAPPING_TARGET_WINDOW_SIZE);
                 // Any opacity higher than this would make InputDispatcher block the touch
                 params.alpha = mInputManager.getMaximumObscuringOpacityForTouch();
                 intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
@@ -319,14 +328,14 @@
         final String windowName = "Test Overlay";
         final AtomicBoolean touchReceived = new AtomicBoolean(false);
         final CompletableFuture<Integer> eventFlags = new CompletableFuture<>();
-
+        final int[] viewOnScreenLocation = new int[2];
         try {
             // Set up a touchable window.
             mActivityRule.runOnUiThread(() -> {
                 mView = new View(mActivity);
                 p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
-                p.width = 100;
-                p.height = 100;
+                p.width = TAPPING_TARGET_WINDOW_SIZE;
+                p.height = TAPPING_TARGET_WINDOW_SIZE;
                 p.gravity = Gravity.CENTER;
                 mView.setOnClickListener((v) -> {
                     mClickCount++;
@@ -337,16 +346,21 @@
                     return false;
                 });
                 mActivity.addWindow(mView, p);
-
+            });
+            mInstrumentation.waitForIdleSync();
+            mActivityRule.runOnUiThread(() -> {
+                mView.getLocationOnScreen(viewOnScreenLocation);
                 // Set up an overlap window from service, use different process.
                 WindowManager.LayoutParams params = getObscuringViewLayoutParams(windowName);
                 params.flags |= FLAG_NOT_TOUCHABLE;
                 // Any opacity higher than this would make InputDispatcher block the touch
                 params.alpha = mInputManager.getMaximumObscuringOpacityForTouch();
+                placeWindowAtLayoutCenter(params, TAPPING_TARGET_WINDOW_SIZE,
+                        viewOnScreenLocation[0], viewOnScreenLocation[1],
+                        TAPPING_TARGET_WINDOW_SIZE);
                 intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                 mActivity.startForegroundService(intent);
             });
-            mInstrumentation.waitForIdleSync();
             waitForWindow(windowName);
             CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);
 
@@ -416,13 +430,14 @@
         intent.setComponent(Components.OVERLAY_TEST_SERVICE);
         final String windowName = "Test Overlay";
         final AtomicBoolean touchReceived = new AtomicBoolean(false);
+        final int[] viewOnScreenLocation = new int[2];
         try {
             mActivityRule.runOnUiThread(() -> {
                 mView = new View(mActivity);
                 mView.setBackgroundColor(Color.GREEN);
                 p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
-                p.width = 100;
-                p.height = 100;
+                p.width = TAPPING_TARGET_WINDOW_SIZE;
+                p.height = TAPPING_TARGET_WINDOW_SIZE;
                 p.gravity = Gravity.CENTER;
                 mView.setOnClickListener((v) -> {
                     mClickCount++;
@@ -433,11 +448,17 @@
                     return false;
                 });
                 mActivity.addWindow(mView, p);
-
+            });
+            mInstrumentation.waitForIdleSync();
+            mActivityRule.runOnUiThread(() -> {
+                mView.getLocationOnScreen(viewOnScreenLocation);
                 // Set up an overlap window from service, use different process.
                 WindowManager.LayoutParams params = getObscuringViewLayoutParams(windowName);
                 params.flags |= FLAG_NOT_TOUCHABLE;
                 params.alpha = MIN_POSITIVE_OPACITY;
+                placeWindowAtLayoutCenter(params, TAPPING_TARGET_WINDOW_SIZE,
+                        viewOnScreenLocation[0], viewOnScreenLocation[1],
+                        TAPPING_TARGET_WINDOW_SIZE);
                 intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                 mActivity.startForegroundService(intent);
             });
@@ -464,14 +485,14 @@
         final String windowName = "Test Overlay";
         final AtomicBoolean touchReceived = new AtomicBoolean(false);
         final CompletableFuture<Integer> eventFlags = new CompletableFuture<>();
-
+        final int[] viewOnScreenLocation = new int[2];
         try {
             mActivityRule.runOnUiThread(() -> {
                 mView = new View(mActivity);
                 mView.setBackgroundColor(Color.GREEN);
                 p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
-                p.width = 100;
-                p.height = 100;
+                p.width = TAPPING_TARGET_WINDOW_SIZE;
+                p.height = TAPPING_TARGET_WINDOW_SIZE;
                 p.gravity = Gravity.CENTER;
                 mView.setOnClickListener((v) -> {
                     mClickCount++;
@@ -482,12 +503,17 @@
                     return false;
                 });
                 mActivity.addWindow(mView, p);
-
+            });
+            mInstrumentation.waitForIdleSync();
+            mActivityRule.runOnUiThread(() -> {
+                mView.getLocationOnScreen(viewOnScreenLocation);
                 // Set up an overlap window from service, use different process.
-                WindowManager.LayoutParams params = getObscuringViewLayoutParams(windowName, 30);
+                WindowManager.LayoutParams params = getObscuringViewLayoutParams(windowName,
+                        PARTIAL_OBSCURING_WINDOW_SIZE);
+                placeWindowAtLayoutCenter(params, PARTIAL_OBSCURING_WINDOW_SIZE,
+                        viewOnScreenLocation[0], viewOnScreenLocation[1], TAPPING_TARGET_WINDOW_SIZE);
                 // Move it off the touch path (center) but still overlap with window above
-                params.y = 30;
-                params.alpha = 0;
+                params.y += PARTIAL_OBSCURING_WINDOW_SIZE;
                 intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                 mActivity.startForegroundService(intent);
             });
@@ -776,6 +802,15 @@
         }
     }
 
+    /** Set a square window to display at the center of a square layout*/
+    static void placeWindowAtLayoutCenter(WindowManager.LayoutParams windowParams, int windowWidth,
+            int layoutLeft, int layoutTop, int layoutWidth) {
+        windowParams.gravity = Gravity.TOP | Gravity.LEFT;
+        int offset = (layoutWidth - windowWidth) / 2;
+        windowParams.x = layoutLeft + offset;
+        windowParams.y = layoutTop + offset;
+    }
+
     /** Helper class to save, set, and restore pointer location preferences. */
     private static class PointerLocationSession extends SettingsSession<Boolean> {
         PointerLocationSession() {
diff --git a/tests/tests/app.usage/AndroidManifest.xml b/tests/tests/app.usage/AndroidManifest.xml
index 71ec3d3..141a9af 100644
--- a/tests/tests/app.usage/AndroidManifest.xml
+++ b/tests/tests/app.usage/AndroidManifest.xml
@@ -51,6 +51,10 @@
         <activity android:name=".FragmentTestActivity" />
         <activity android:name=".TaskRootActivity" />
         <service android:name=".TestService" />
+        <service android:name=".TestJob"
+            android:exported="true"
+            android:permission="android.permission.BIND_JOB_SERVICE"
+        />
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/TestJob.java b/tests/tests/app.usage/src/android/app/usage/cts/TestJob.java
new file mode 100644
index 0000000..decc9d8
--- /dev/null
+++ b/tests/tests/app.usage/src/android/app/usage/cts/TestJob.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.usage.cts;
+
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.content.ComponentName;
+import android.content.Context;
+
+import java.util.function.BooleanSupplier;
+
+public final class TestJob extends JobService {
+
+    public static final int TEST_JOB_ID = 1;
+    public static final String NOTIFICATION_CHANNEL_ID = TestJob.class.getSimpleName();
+    private static boolean sJobStarted;
+    public static BooleanSupplier hasJobStarted = new BooleanSupplier() {
+        @Override
+        public boolean getAsBoolean() {
+            return sJobStarted;
+        }
+    };
+
+    @Override
+    public boolean onStartJob(JobParameters params) {
+        sJobStarted = true;
+        return false;
+    }
+
+    @Override
+    public boolean onStopJob(JobParameters params) {
+        return false;
+    }
+
+    public static void schedule(Context context) {
+        sJobStarted = false;
+        JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
+        ComponentName componentName = new ComponentName(context, TestJob.class);
+
+        JobInfo jobInfo = new JobInfo.Builder(TEST_JOB_ID, componentName).build();
+        jobScheduler.schedule(jobInfo);
+    }
+}
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 5f12ea7..51321b1 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -115,6 +115,8 @@
 
     private static final String DELETE_SHELL_COMMAND = "settings delete global ";
 
+    private static final String JOBSCHEDULER_RUN_SHELL_COMMAND = "cmd jobscheduler run";
+
     private static final String TEST_APP_PKG = "android.app.usage.cts.test1";
     private static final String TEST_APP_CLASS = "android.app.usage.cts.test1.SomeActivity";
     private static final String TEST_APP_CLASS_LOCUS
@@ -248,7 +250,7 @@
 
     @AppModeFull(reason = "No usage events access in instant apps")
     @Test
-    public void testLastAnyTimeComponentUsed_launchActivity() throws Exception {
+    public void testLastTimeAnyComponentUsed_launchActivityShouldBeDetected() throws Exception {
         mUiDevice.wakeUp();
         dismissKeyguard(); // also want to start out with the keyguard dismissed.
 
@@ -256,33 +258,62 @@
         launchSubActivity(Activities.ActivityOne.class);
         final long endTime = System.currentTimeMillis();
 
-        final Map<String, UsageStats> map = mUsageStatsManager.queryAndAggregateUsageStats(
-                startTime, endTime);
-        final UsageStats stats = map.get(mTargetPackage);
-        assertNotNull(stats);
-        final long lastTimeComponentUsed = stats.getLastTimeAnyComponentUsed();
-        assertLessThan(startTime, lastTimeComponentUsed);
-        assertLessThan(lastTimeComponentUsed, endTime);
+        verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, mTargetPackage);
     }
 
     @AppModeFull(reason = "No usage events access in instant apps")
     @Test
-    public void testLastTimeAnyComponentUsedGlobal_launchActivity() throws Exception {
+    public void testLastTimeAnyComponentUsed_bindServiceShouldBeDetected() throws Exception {
         mUiDevice.wakeUp();
-        dismissKeyguard();
+        dismissKeyguard(); // also want to start out with the keyguard dismissed.
 
-        final long startDay = System.currentTimeMillis() / TimeUnit.DAYS.toMillis(1)
-                * TimeUnit.DAYS.toMillis(1);
-        launchSubActivity(Activities.ActivityOne.class);
-        final long endDay = System.currentTimeMillis() / TimeUnit.DAYS.toMillis(1)
-                * TimeUnit.DAYS.toMillis(1);
+        final long startTime = System.currentTimeMillis();
+        bindToTestService();
+        final long endTime = System.currentTimeMillis();
 
-        final long lastTimeAnyComponentUsed =
-                mUsageStatsManager.getLastTimeAnyComponentUsed(mTargetPackage);
-        assertLessThanOrEqual(startDay, lastTimeAnyComponentUsed);
-        assertLessThanOrEqual(lastTimeAnyComponentUsed, endDay);
+        verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
     }
 
+    private void verifyLastTimeAnyComponentUsedWithinRange(
+            long startTime, long endTime, String targetPackage) {
+        final Map<String, UsageStats> map = mUsageStatsManager.queryAndAggregateUsageStats(
+                startTime, endTime);
+        final UsageStats stats = map.get(targetPackage);
+        assertNotNull(stats);
+        final long lastTimeAnyComponentUsed = stats.getLastTimeAnyComponentUsed();
+        assertLessThan(startTime, lastTimeAnyComponentUsed);
+        assertLessThan(lastTimeAnyComponentUsed, endTime);
+
+        final long lastDayAnyComponentUsedGlobal =
+                mUsageStatsManager.getLastTimeAnyComponentUsed(targetPackage) / DAY;
+        assertLessThanOrEqual(startTime / DAY, lastDayAnyComponentUsedGlobal);
+        assertLessThanOrEqual(lastDayAnyComponentUsedGlobal, endTime / DAY);
+    }
+
+    @AppModeFull(reason = "No usage events access in instant apps")
+    @Test
+    public void testLastTimeAnyComponentUsed_JobServiceShouldBeIngnored() throws Exception {
+        mUiDevice.wakeUp();
+        dismissKeyguard(); // also want to start out with the keyguard dismissed.
+
+        final long startTime = System.currentTimeMillis();
+        runJobImmediately();
+        waitUntil(TestJob.hasJobStarted, /* expected */ true);
+
+        final Map<String, UsageStats> map = mUsageStatsManager.queryAndAggregateUsageStats(
+                startTime, System.currentTimeMillis());
+        final UsageStats stats = map.get(mTargetPackage);
+        if (stats != null) {
+            final long lastTimeAnyComponentUsed = stats.getLastTimeAnyComponentUsed();
+            // Check that the usage is NOT detected.
+            assertLessThanOrEqual(lastTimeAnyComponentUsed, startTime);
+        }
+
+        final long lastDayAnyComponentUsedGlobal =
+                mUsageStatsManager.getLastTimeAnyComponentUsed(mTargetPackage) / DAY;
+        // Check that the usage is NOT detected.
+        assertLessThanOrEqual(lastDayAnyComponentUsedGlobal, startTime / DAY);
+    }
 
     @AppModeFull(reason = "No usage events access in instant apps")
     @Test
@@ -1769,6 +1800,13 @@
         }
     }
 
+    private void runJobImmediately() throws Exception {
+        TestJob.schedule(mContext);
+        executeShellCmd(JOBSCHEDULER_RUN_SHELL_COMMAND
+                + " " + mContext.getPackageName()
+                + " " + TestJob.TEST_JOB_ID);
+    }
+
     private boolean isAppInactiveAsPermissionlessApp(String pkg) throws Exception {
         final ITestReceiver testService = bindToTestService();
         return testService.isAppInactive(pkg);
diff --git a/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java b/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
index 78776ba..98f1377 100644
--- a/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
+++ b/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
@@ -84,6 +84,7 @@
 import android.os.RemoteCallback;
 import android.os.UserHandle;
 import android.util.SparseArray;
+import android.view.accessibility.AccessibilityManager;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -239,6 +240,9 @@
                         .getString(Intent.EXTRA_INSTALLER_PACKAGE_NAME);
                 sendSetInstallerPackageName(remoteCallback, targetPackageName,
                         installerPackageName);
+            } else if (Constants.ACTION_GET_INSTALLED_ACCESSIBILITYSERVICES_PACKAGES.equals(
+                    action)) {
+                sendGetInstalledAccessibilityServicePackages(remoteCallback);
             } else {
                 sendError(remoteCallback, new Exception("unknown action " + action));
             }
@@ -247,6 +251,16 @@
         }
     }
 
+    private void sendGetInstalledAccessibilityServicePackages(RemoteCallback remoteCallback) {
+        final String[] packages = getSystemService(
+                AccessibilityManager.class).getInstalledAccessibilityServiceList().stream().map(
+                p -> p.getComponentName().getPackageName()).distinct().toArray(String[]::new);
+        final Bundle result = new Bundle();
+        result.putStringArray(EXTRA_RETURN_RESULT, packages);
+        remoteCallback.sendResult(result);
+        finish();
+    }
+
     private void onCommandReady(Intent intent) {
         final RemoteCallback callback = intent.getParcelableExtra(EXTRA_REMOTE_READY_CALLBACK);
         if (callback != null) {
diff --git a/tests/tests/appenumeration/app/target/AndroidManifest-filters.xml b/tests/tests/appenumeration/app/target/AndroidManifest-filters.xml
index 59ec446..eeb3170 100644
--- a/tests/tests/appenumeration/app/target/AndroidManifest-filters.xml
+++ b/tests/tests/appenumeration/app/target/AndroidManifest-filters.xml
@@ -74,5 +74,16 @@
                 <action android:name="android.appenumeration.action.BROADCAST_UNEXPORTED"/>
             </intent-filter>
         </receiver>
+        <service android:name="android.appenumeration.testapp.StubAccessibilityService"
+                 android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+                 android:exported="true">
+            <intent-filter>
+                <action android:name="android.accessibilityservice.AccessibilityService"/>
+                <category android:name="android.accessibilityservice.category.FEEDBACK_GENERIC"/>
+            </intent-filter>
+
+            <meta-data android:name="android.accessibilityservice"
+                       android:resource="@xml/stub_accessibility_service"/>
+        </service>
     </application>
 </manifest>
diff --git a/tests/tests/appenumeration/app/target/res/values/strings.xml b/tests/tests/appenumeration/app/target/res/values/strings.xml
new file mode 100644
index 0000000..23e2713
--- /dev/null
+++ b/tests/tests/appenumeration/app/target/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+
+    <!-- String description for the test accessibility service -->
+    <string name="stub_accessibility_service">stubAccessibililityService</string>
+
+</resources>
diff --git a/tests/tests/appenumeration/app/target/res/xml/stub_accessibility_service.xml b/tests/tests/appenumeration/app/target/res/xml/stub_accessibility_service.xml
new file mode 100644
index 0000000..e202f36
--- /dev/null
+++ b/tests/tests/appenumeration/app/target/res/xml/stub_accessibility_service.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
+                       android:description="@string/stub_accessibility_service"
+                       android:accessibilityEventTypes="typeAllMask"
+                       android:accessibilityFeedbackType="feedbackGeneric"
+                       android:notificationTimeout="0" />
diff --git a/tests/tests/appenumeration/app/target/src/android/appenumeration/testapp/StubAccessibilityService.java b/tests/tests/appenumeration/app/target/src/android/appenumeration/testapp/StubAccessibilityService.java
new file mode 100644
index 0000000..aa34f54
--- /dev/null
+++ b/tests/tests/appenumeration/app/target/src/android/appenumeration/testapp/StubAccessibilityService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.appenumeration.testapp;
+
+import android.accessibilityservice.AccessibilityService;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * A stub accessibility service to verify the package visibility of {@link
+ * android.view.accessibility.AccessibilityManager}.
+ */
+public class StubAccessibilityService extends AccessibilityService {
+    @Override
+    public void onAccessibilityEvent(AccessibilityEvent event) {
+    }
+
+    @Override
+    public void onInterrupt() {
+    }
+}
diff --git a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
index 740470e..c93016b 100644
--- a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
+++ b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
@@ -205,7 +205,8 @@
             PKG_BASE + "cts.action.GET_PREFERRED_ACTIVITIES";
     public static final String ACTION_SET_INSTALLER_PACKAGE_NAME =
             PKG_BASE + "cts.action.SET_INSTALLER_PACKAGE_NAME";
-
+    public static final String ACTION_GET_INSTALLED_ACCESSIBILITYSERVICES_PACKAGES =
+            PKG_BASE + "cts.action.GET_INSTALLED_ACCESSIBILITYSERVICES_PACKAGES";
     public static final String EXTRA_REMOTE_CALLBACK = "remoteCallback";
     public static final String EXTRA_REMOTE_READY_CALLBACK = "remoteReadyCallback";
     public static final String EXTRA_ERROR = "error";
diff --git a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
index 4a26aaf..123808e 100644
--- a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
+++ b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
@@ -20,6 +20,7 @@
 import static android.appenumeration.cts.Constants.ACTION_AWAIT_LAUNCHER_APPS_CALLBACK;
 import static android.appenumeration.cts.Constants.ACTION_BIND_SERVICE;
 import static android.appenumeration.cts.Constants.ACTION_CHECK_SIGNATURES;
+import static android.appenumeration.cts.Constants.ACTION_GET_INSTALLED_ACCESSIBILITYSERVICES_PACKAGES;
 import static android.appenumeration.cts.Constants.ACTION_GET_INSTALLED_APPWIDGET_PROVIDERS;
 import static android.appenumeration.cts.Constants.ACTION_GET_INSTALLED_PACKAGES;
 import static android.appenumeration.cts.Constants.ACTION_GET_NAMES_FOR_UIDS;
@@ -649,6 +650,21 @@
         assertVisible(QUERIES_WILDCARD_SHARE, TARGET_SHARE);
     }
 
+    @Test
+    public void queriesNothing_cannotSeeA11yService() throws Exception {
+        if (!sGlobalFeatureEnabled) return;
+        final String[] result = getInstalledAccessibilityServices(QUERIES_NOTHING);
+        assertThat(result, not(hasItemInArray(TARGET_FILTERS)));
+    }
+
+    @Test
+    public void queriesNothingHasPermission_canSeeA11yService() throws Exception {
+        if (!sGlobalFeatureEnabled) return;
+        final String[] result = getInstalledAccessibilityServices(QUERIES_NOTHING_PERM);
+        assertThat(QUERIES_NOTHING_PERM + " should be able to see " + TARGET_FILTERS,
+                result, hasItemInArray(TARGET_FILTERS));
+    }
+
     private void assertVisible(String sourcePackageName, String targetPackageName)
             throws Exception {
         if (!sGlobalFeatureEnabled) return;
@@ -1183,6 +1199,13 @@
         }
     }
 
+    private String[] getInstalledAccessibilityServices (String sourcePackageName)
+            throws Exception {
+        final Bundle response = sendCommandBlocking(sourcePackageName, null /*targetPackageName*/,
+                null /*queryIntent*/, ACTION_GET_INSTALLED_ACCESSIBILITYSERVICES_PACKAGES);
+        return response.getStringArray(Intent.EXTRA_RETURN_RESULT);
+    }
+
     private PackageInfo getPackageInfo(String sourcePackageName, String targetPackageName)
             throws Exception {
         Bundle response = sendCommandBlocking(sourcePackageName, targetPackageName,
diff --git a/tests/tests/content/src/android/content/cts/ContentProviderTest.java b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
index 3a84a91..a2b4d83 100644
--- a/tests/tests/content/src/android/content/cts/ContentProviderTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
@@ -40,6 +40,7 @@
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
+import android.platform.test.annotations.AppModeFull;
 import android.provider.MediaStore;
 
 import androidx.test.core.app.ApplicationProvider;
@@ -336,6 +337,7 @@
 
     @Test
     @EnsureHasWorkProfile
+    @AppModeFull
     public void createContentUriForUser_returnsCorrectUri() {
         final ContentResolver profileContentResolver =
                 sTestApis.context().androidContextAsUser(sDeviceState.workProfile())
diff --git a/tests/tests/content/src/android/content/cts/ContextTest.java b/tests/tests/content/src/android/content/cts/ContextTest.java
index 0799704..29e295a 100644
--- a/tests/tests/content/src/android/content/cts/ContextTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextTest.java
@@ -79,9 +79,7 @@
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
 
 @AppModeFull // TODO(Instant) Figure out which APIs should work.
 public class ContextTest extends AndroidTestCase {
@@ -237,6 +235,33 @@
         assertEquals("baz", params.getNextAttributionSource().getAttributionTag());
     }
 
+    public void testAttributionSourceSetNext() throws Exception {
+        final AttributionSource next = new AttributionSource.Builder(2)
+                .setPackageName("nextBar")
+                .setAttributionTag("nextBaz")
+                .build();
+        final ContextParams params = new ContextParams.Builder()
+                .setAttributionTag("foo")
+                .setNextAttributionSource(new AttributionSource.Builder(1)
+                        .setPackageName("bar")
+                        .setAttributionTag("baz")
+                        .setNext(next)
+                        .build())
+                .build();
+
+        // Setting a 'next' should not affect prev.
+        assertEquals("foo", params.getAttributionTag());
+        assertEquals(1, params.getNextAttributionSource().getUid());
+        assertEquals("bar", params.getNextAttributionSource().getPackageName());
+        assertEquals("baz", params.getNextAttributionSource().getAttributionTag());
+
+        final AttributionSource check =
+                params.getNextAttributionSource().getNext();
+        assertEquals(2, check.getUid());
+        assertEquals("nextBar", check.getPackageName());
+        assertEquals("nextBaz", check.getAttributionTag());
+    }
+
     public void testContextParams_Inherit() throws Exception {
         final ContextParams orig = new ContextParams.Builder()
                 .setAttributionTag("foo").build();
diff --git a/tests/tests/content/src/android/content/pm/cts/FeatureTest.java b/tests/tests/content/src/android/content/pm/cts/FeatureTest.java
index beab1c4..68edc76 100644
--- a/tests/tests/content/src/android/content/pm/cts/FeatureTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/FeatureTest.java
@@ -32,12 +32,14 @@
 public class FeatureTest extends AndroidTestCase {
 
     private static final String TAG = "FeatureTest";
+    private static final long TWO_GB = 1536000000; // 2 GB
 
     private PackageManager mPackageManager;
     private ActivityManager mActivityManager;
     private WindowManager mWindowManager;
     private boolean mSupportsDeviceAdmin;
     private boolean mSupportsManagedProfiles;
+    private long mTotalMemory;
 
     @Override
     protected void setUp() throws Exception {
@@ -49,6 +51,9 @@
                 mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
         mSupportsManagedProfiles =
                 mPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS);
+        ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
+        mActivityManager.getMemoryInfo(memInfo);
+        mTotalMemory = memInfo.totalMem;
     }
 
     /**
@@ -76,8 +81,8 @@
             return;
         }
 
-        // Skip the tests for low-RAM devices
-        if (mActivityManager.isLowRamDevice()) {
+        // Skip the tests for devices with less than 2GB of ram available
+        if (lessThanTwoGbDevice()) {
             return;
         }
 
@@ -107,4 +112,9 @@
         double heightInInchesSquared = Math.pow(dm.heightPixels/dm.ydpi,2);
         return Math.sqrt(widthInInchesSquared + heightInInchesSquared);
     }
+
+    // Implementation copied from CoreGmsAppsTest#twoGbDevice()
+    private boolean lessThanTwoGbDevice() {
+        return mTotalMemory < TWO_GB;
+    }
 }
diff --git a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
index 1c8dcc5..70cb272 100644
--- a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
@@ -24,10 +24,12 @@
 import android.media.MediaCodecList;
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
+import android.os.Build;
 import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 import android.view.Surface;
 
+import com.android.compatibility.common.util.ApiLevelUtil;
 import com.android.compatibility.common.util.MediaUtils;
 
 import android.opengl.GLES20;
@@ -51,6 +53,8 @@
     private boolean verify = false;
     private static final int MIN_FRAMES_BEFORE_DRC = 2;
 
+    private static boolean sIsAtLeastS = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S);
+
     public Iterable<Codec> H264(CodecFactory factory) {
         return factory.createCodecList(
                 MediaFormat.MIMETYPE_VIDEO_AVC,
@@ -1058,9 +1062,12 @@
                 // Previous dequeue was output format change; format change must
                 // correspond to a new sequence, so it must happen right before
                 // the first frame of one of the sequences.
-                assertTrue("cannot find formatchange " + info.presentationTimeUs +
+                // this part of test is new for Android12
+                if (sIsAtLeastS) {
+                    assertTrue("Codec " + getName() + " cannot find formatchange " + info.presentationTimeUs +
                         " in " + mFirstQueueTimestamps,
                         mFirstQueueTimestamps.remove(info.presentationTimeUs));
+                }
                 mOutputFormatChanged = false;
             }
 
diff --git a/tests/tests/media/src/android/media/cts/CodecState.java b/tests/tests/media/src/android/media/cts/CodecState.java
index 1bb0aa5..199c032 100644
--- a/tests/tests/media/src/android/media/cts/CodecState.java
+++ b/tests/tests/media/src/android/media/cts/CodecState.java
@@ -49,7 +49,9 @@
     private LinkedList<Integer> mAvailableOutputBufferIndices;
     private LinkedList<MediaCodec.BufferInfo> mAvailableOutputBufferInfos;
     private volatile long mPresentationTimeUs;
-    private long mSampleBaseTimeUs;
+    private long mFirstSampleTimeUs;
+    private long mPlaybackStartTimeUs;
+    private long mLastPresentTimeUs;
     private MediaCodec mCodec;
     private MediaTimeProvider mMediaTimeProvider;
     private MediaExtractor mExtractor;
@@ -60,6 +62,9 @@
     /** A list of reported rendered video frames' timestamps. */
     private ArrayList<Long> mRenderedVideoFrameTimestampList;
 
+    /** If true the video/audio will start from the beginning when it reaches the end. */
+    private boolean mLoopEnabled = false;
+
     /**
      * Manages audio and video playback using MediaCodec and AudioTrack.
      */
@@ -80,7 +85,9 @@
         mLimitQueueDepth = limitQueueDepth;
         mTunneled = tunneled;
         mAudioSessionId = audioSessionId;
-        mSampleBaseTimeUs = -1;
+        mFirstSampleTimeUs = -1;
+        mPlaybackStartTimeUs = 0;
+        mLastPresentTimeUs = 0;
 
         mCodec = codec;
 
@@ -221,6 +228,10 @@
         return sampleTime;
     }
 
+    public void setLoopEnabled(boolean enabled) {
+        mLoopEnabled = enabled;
+    }
+
     /**
      * Extracts some data from the configured MediaExtractor and feeds it to the configured
      * MediaCodec.
@@ -260,30 +271,38 @@
             }
 
             if (mTunneled && !mIsAudio) {
-                if (mSampleBaseTimeUs == -1) {
-                    mSampleBaseTimeUs = sampleTime;
+                if (mFirstSampleTimeUs == -1) {
+                    mFirstSampleTimeUs = sampleTime;
                 }
-                sampleTime -= mSampleBaseTimeUs;
+                sampleTime -= mFirstSampleTimeUs;
             }
 
+            mLastPresentTimeUs = mPlaybackStartTimeUs + sampleTime;
+
             if ((sampleFlags & MediaExtractor.SAMPLE_FLAG_ENCRYPTED) != 0) {
                 MediaCodec.CryptoInfo info = new MediaCodec.CryptoInfo();
                 mExtractor.getSampleCryptoInfo(info);
 
                 mCodec.queueSecureInputBuffer(
-                        inputBufferIndex, 0 /* offset */, info, sampleTime, 0 /* flags */);
+                        inputBufferIndex, 0 /* offset */, info, mLastPresentTimeUs, 0 /* flags */);
             } else {
                 mCodec.queueInputBuffer(
-                        inputBufferIndex, 0 /* offset */, sampleSize, sampleTime, 0 /* flags */);
+                        inputBufferIndex, 0 /* offset */, sampleSize, mLastPresentTimeUs, 0 /* flags */);
             }
 
             mExtractor.advance();
-            return sampleTime;
+            return mLastPresentTimeUs;
         } else if (trackIndex < 0) {
             Log.d(TAG, "saw input EOS on track " + mTrackIndex);
 
-            mSawInputEOS = true;
+            if (mLoopEnabled) {
+                Log.d(TAG, "looping from the beginning");
+                mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+                mPlaybackStartTimeUs = mLastPresentTimeUs;
+                return null;
+            }
 
+            mSawInputEOS = true;
             mCodec.queueInputBuffer(
                     inputBufferIndex, 0 /* offset */, 0 /* sampleSize */,
                     0 /* sampleTime */, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
@@ -344,7 +363,7 @@
             mSawOutputEOS = true;
 
             // Do not stop audio track here. Video presentation may not finish
-            // yet, stopping the auido track now would result in getAudioTimeUs
+            // yet, stopping the audio track now would result in getAudioTimeUs
             // returning 0 and prevent video samples from being presented.
             // We stop the audio track before the playback thread exits.
             return false;
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 1db1c59..b2a888d 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -3623,7 +3623,7 @@
 
         AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
         mMediaCodecPlayer = new MediaCodecTunneledPlayer(
-                getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
+                mContext, getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
 
         Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
         mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
@@ -3692,7 +3692,7 @@
 
         AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
         mMediaCodecPlayer = new MediaCodecTunneledPlayer(
-                getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
+                mContext, getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
 
         Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
         mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
@@ -3748,7 +3748,7 @@
 
         AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
         mMediaCodecPlayer = new MediaCodecTunneledPlayer(
-                getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
+                mContext, getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
 
         Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
         mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
@@ -3826,7 +3826,7 @@
         // Setup tunnel mode test media player
         AudioManager am = mContext.getSystemService(AudioManager.class);
         mMediaCodecPlayer = new MediaCodecTunneledPlayer(
-                getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
+                mContext, getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
 
         Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
         mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
@@ -3922,7 +3922,7 @@
 
         AudioManager am = mContext.getSystemService(AudioManager.class);
         mMediaCodecPlayer = new MediaCodecTunneledPlayer(
-                getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
+                mContext, getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
 
         Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
         mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTunneledPlayer.java b/tests/tests/media/src/android/media/cts/MediaCodecTunneledPlayer.java
index bc3ae6e..677e644 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTunneledPlayer.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTunneledPlayer.java
@@ -15,6 +15,7 @@
  */
 package android.media.cts;
 
+import android.content.Context;
 import android.media.AudioTimestamp;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
@@ -64,11 +65,13 @@
     private Uri mVideoUri;
     private boolean mTunneled;
     private int mAudioSessionId;
+    private Context mContext;
 
     /*
      * Media player class to playback video using tunneled MediaCodec.
      */
-    public MediaCodecTunneledPlayer(SurfaceHolder holder, boolean tunneled, int AudioSessionId) {
+    public MediaCodecTunneledPlayer(Context context, SurfaceHolder holder, boolean tunneled, int AudioSessionId) {
+        mContext = context;
         mSurfaceHolder = holder;
         mTunneled = tunneled;
         mAudioTrackState = null;
@@ -203,8 +206,8 @@
             }
         }
 
-        mAudioExtractor.setDataSource(mAudioUri.toString(), mAudioHeaders);
-        mVideoExtractor.setDataSource(mVideoUri.toString(), mVideoHeaders);
+        mAudioExtractor.setDataSource(mContext, mAudioUri, mAudioHeaders);
+        mVideoExtractor.setDataSource(mContext, mVideoUri, mVideoHeaders);
 
         if (null == mVideoCodecStates) {
             mVideoCodecStates = new HashMap<Integer, CodecState>();
@@ -406,6 +409,25 @@
         }
     }
 
+    /**
+     * Enables or disables looping. Should be called after {@link #prepare()}.
+     */
+    public void setLoopEnabled(boolean enabled) {
+        synchronized (mState) {
+            if (mVideoCodecStates != null) {
+                for (CodecState state : mVideoCodecStates.values()) {
+                    state.setLoopEnabled(enabled);
+                }
+            }
+
+            if (mAudioCodecStates != null) {
+                for (CodecState state : mAudioCodecStates.values()) {
+                    state.setLoopEnabled(enabled);
+                }
+            }
+        }
+    }
+
     public void reset() {
         synchronized (mState) {
             if (mState == STATE_PLAYING) {
@@ -444,7 +466,7 @@
         try {
             mThread.join();
         } catch (InterruptedException ex) {
-            Log.d(TAG, "mThread.join " + ex);
+            Log.d(TAG, "mThread.join ", ex);
         }
     }
 
@@ -470,7 +492,7 @@
                 state.doSomeWork();
             }
         } catch (IllegalStateException e) {
-            throw new Error("Video CodecState.doSomeWork" + e);
+            throw new Error("Video CodecState.doSomeWork", e);
         }
 
         try {
@@ -478,7 +500,7 @@
                 state.doSomeWork();
             }
         } catch (IllegalStateException e) {
-            throw new Error("Audio CodecState.doSomeWork" + e);
+            throw new Error("Audio CodecState.doSomeWork", e);
         }
 
     }
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt b/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
index a7e893d..e2718df 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
@@ -21,8 +21,8 @@
 import android.content.Intent
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageManager
-import android.os.Build
 import android.net.Uri
+import android.os.Build
 import android.platform.test.annotations.AppModeFull
 import android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION
 import android.provider.Settings
@@ -114,9 +114,8 @@
                         packageManager.getApplicationInfo(APK_PACKAGE_NAME_S_APP, 0 /* flags */)
                     val stopped = ((ai.flags and ApplicationInfo.FLAG_STOPPED) != 0)
                     assertTrue(stopped)
-                    runShellCommandOrThrow("cmd statusbar expand-notifications")
-                    waitFindObject(By.textContains("unused app"))
-                        .click()
+                    openUnusedAppsNotification()
+
                     waitFindObject(By.text(APK_PACKAGE_NAME_S_APP))
                 }
             }
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
index faae778..da55409 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
@@ -21,26 +21,46 @@
 import android.app.Instrumentation
 import android.app.UiAutomation
 import android.content.Context
+import android.content.pm.PackageManager
 import android.os.ParcelFileDescriptor
 import android.os.Process
 import android.provider.DeviceConfig
+import android.support.test.uiautomator.By
 import android.support.test.uiautomator.BySelector
+import android.support.test.uiautomator.UiDevice
 import android.support.test.uiautomator.UiObject2
+import android.support.test.uiautomator.UiScrollable
+import android.support.test.uiautomator.UiSelector
+import android.support.test.uiautomator.Until
 import androidx.test.InstrumentationRegistry
+import com.android.compatibility.common.util.ExceptionUtils.wrappingExceptions
 import com.android.compatibility.common.util.LogcatInspector
 import com.android.compatibility.common.util.SystemUtil.eventually
 import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
 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
 import com.android.compatibility.common.util.click
 import com.android.compatibility.common.util.depthFirstSearch
 import com.android.compatibility.common.util.textAsString
 import org.hamcrest.Matcher
 import org.hamcrest.Matchers
+import org.junit.Assert
 import org.junit.Assert.assertThat
 import java.io.InputStream
 
+const val SYSUI_PKG_NAME = "com.android.systemui"
+const val NOTIF_LIST_ID = "com.android.systemui:id/notification_stack_scroller"
+const val CLEAR_ALL_BUTTON_ID = "dismiss_text"
+// Time to find a notification. Unlikely, but in cases with a lot of notifications, it may take
+// time to find the notification we're looking for
+const val NOTIF_FIND_TIMEOUT = 20000L
+const val VIEW_WAIT_TIMEOUT = 1000L
+
+const val CMD_EXPAND_NOTIFICATIONS = "cmd statusbar expand-notifications"
+const val CMD_COLLAPSE = "cmd statusbar collapse"
+
 const val APK_PATH_S_APP = "/data/local/tmp/cts/os/CtsAutoRevokeSApp.apk"
 const val APK_PACKAGE_NAME_S_APP = "android.os.cts.autorevokesapp"
 const val APK_PATH_R_APP = "/data/local/tmp/cts/os/CtsAutoRevokeRApp.apk"
@@ -148,6 +168,82 @@
     runShellCommandOrThrow("input keyevent KEYCODE_HOME")
 }
 
+/**
+ * Open the "unused apps" notification which is sent after the hibernation job.
+ */
+fun openUnusedAppsNotification() {
+    val notifSelector = By.textContains("unused app")
+    if (hasFeatureWatch()) {
+        val uiAutomation = InstrumentationRegistry.getInstrumentation().uiAutomation
+        expandNotificationsWatch(UiAutomatorUtils.getUiDevice())
+        waitFindObject(uiAutomation, notifSelector).click()
+        // In wear os, notification has one additional button to open it
+        waitFindObject(uiAutomation, By.text("Open")).click()
+    } else {
+        runShellCommandOrThrow(CMD_EXPAND_NOTIFICATIONS)
+        waitFindNotification(notifSelector, NOTIF_FIND_TIMEOUT).click()
+    }
+}
+
+fun hasFeatureWatch(): Boolean {
+    return InstrumentationRegistry.getTargetContext().packageManager.hasSystemFeature(
+        PackageManager.FEATURE_WATCH)
+}
+
+private fun expandNotificationsWatch(uiDevice: UiDevice) {
+    with(uiDevice) {
+        wakeUp()
+        // Swipe up from bottom to reveal notifications
+        val x = displayWidth / 2
+        swipe(x, displayHeight, x, 0, 1)
+    }
+}
+
+/**
+ * Reset to the top of the notifications list.
+ */
+private fun resetNotifications(notificationList: UiScrollable) {
+    runShellCommandOrThrow(CMD_COLLAPSE)
+    notificationList.waitUntilGone(VIEW_WAIT_TIMEOUT)
+    runShellCommandOrThrow(CMD_EXPAND_NOTIFICATIONS)
+}
+
+private fun waitFindNotification(selector: BySelector, timeoutMs: Long):
+    UiObject2 {
+    var view: UiObject2? = null
+    val start = System.currentTimeMillis()
+    val uiDevice = UiAutomatorUtils.getUiDevice()
+
+    var isAtEnd = false
+    var wasScrolledUpAlready = false
+    while (view == null && start + timeoutMs > System.currentTimeMillis()) {
+        view = uiDevice.wait(Until.findObject(selector), VIEW_WAIT_TIMEOUT)
+        if (view == null) {
+            val notificationList = UiScrollable(UiSelector().resourceId(NOTIF_LIST_ID))
+            wrappingExceptions({ cause: Throwable? -> UiDumpUtils.wrapWithUiDump(cause) }) {
+                Assert.assertTrue("Notification list view not found",
+                    notificationList.waitForExists(VIEW_WAIT_TIMEOUT))
+            }
+            if (isAtEnd) {
+                if (wasScrolledUpAlready) {
+                    break
+                }
+                resetNotifications(notificationList)
+                isAtEnd = false
+                wasScrolledUpAlready = true
+            } else {
+                notificationList.scrollForward()
+                isAtEnd = uiDevice.hasObject(By.res(SYSUI_PKG_NAME, CLEAR_ALL_BUTTON_ID))
+            }
+        }
+    }
+    wrappingExceptions({ cause: Throwable? -> UiDumpUtils.wrapWithUiDump(cause) }) {
+        Assert.assertNotNull("View not found after waiting for " + timeoutMs + "ms: " + selector,
+            view)
+    }
+    return view!!
+}
+
 fun waitFindObject(uiAutomation: UiAutomation, selector: BySelector): UiObject2 {
     try {
         return UiAutomatorUtils.waitFindObject(selector)
diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
index e17883c..d5cc564 100644
--- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
+++ b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
@@ -31,7 +31,6 @@
 import android.platform.test.annotations.AppModeFull
 import android.support.test.uiautomator.By
 import android.support.test.uiautomator.BySelector
-import android.support.test.uiautomator.UiDevice
 import android.support.test.uiautomator.UiObject2
 import android.support.test.uiautomator.UiObjectNotFoundException
 import android.view.accessibility.AccessibilityNodeInfo
@@ -84,7 +83,6 @@
 
     private val context: Context = InstrumentationRegistry.getTargetContext()
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
-    private val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
 
     private val mPermissionControllerResources: Resources = context.createPackageContext(
             context.packageManager.permissionControllerPackageName, 0).resources
@@ -392,19 +390,6 @@
         assertPermission(PERMISSION_GRANTED)
     }
 
-    private fun openUnusedAppsNotification() {
-        if (hasFeatureWatch()) {
-            expandNotificationsWatch()
-        } else {
-            runShellCommandOrThrow("cmd statusbar expand-notifications")
-        }
-        waitFindObject(By.textContains("unused app")).click()
-        if (hasFeatureWatch()) {
-            // In wear os, notification has one additional button to open it
-            waitFindObject(By.text("Open")).click()
-        }
-    }
-
     private fun goBack() {
         runShellCommandOrThrow("input keyevent KEYCODE_BACK")
     }
@@ -500,19 +485,6 @@
         waitForIdle()
     }
 
-    private fun hasFeatureWatch(): Boolean {
-        return context.packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
-    }
-
-    private fun expandNotificationsWatch() {
-        with(uiDevice) {
-            wakeUp()
-            // Swipe up from bottom to reveal notifications
-            val x = displayWidth / 2
-            swipe(x, displayHeight, x, 0, 1)
-        }
-    }
-
     private fun assertAllowlistState(state: Boolean) {
         assertThat(
             waitFindObject(By.textStartsWith("Auto-revoke allowlisted: ")).text,
diff --git a/tests/tests/permission2/res/raw/automotive_android_manifest.xml b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
index 41b34e9..ff9bbcf 100644
--- a/tests/tests/permission2/res/raw/automotive_android_manifest.xml
+++ b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
@@ -410,6 +410,76 @@
          android:label="@string/car_permission_label_car_test_service"
          android:description="@string/car_permission_desc_car_test_service"/>
 
+    <permission android:name="android.car.permission.ACCESS_PRIVATE_DISPLAY_ID"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_access_private_display_id"
+        android:description="@string/car_permission_desc_access_private_display_id"/>
+
+    <permission android:name="android.car.permission.MONITOR_CAR_EVS_STATUS"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_monitor_evs_status"
+        android:description="@string/car_permission_desc_monitor_evs_status"/>
+
+    <permission android:name="android.car.permission.CONTROL_CAR_POWER_POLICY"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_control_car_power_policy"
+        android:description="@string/car_permission_desc_control_car_power_policy"/>
+
+    <permission android:name="android.car.permission.COLLECT_CAR_WATCHDOG_METRICS"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_collect_car_watchdog_metrics"
+        android:description="@string/car_permission_desc_collect_car_watchdog_metrics"/>
+
+    <permission android:name="android.car.permission.USE_CAR_TELEMETRY_SERVICE"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_use_telemetry_service"
+        android:description="@string/car_permission_desc_use_telemetry_service"/>
+
+    <permission android:name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_control_evs_activity"
+        android:description="@string/car_permission_desc_control_evs_activity"/>
+
+    <permission android:name="android.car.permission.REQUEST_CAR_EVS_ACTIVITY"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_request_evs_activity"
+        android:description="@string/car_permission_desc_request_evs_activity"/>
+
+    <permission android:name="android.car.permission.USE_CAR_EVS_CAMERA"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_use_evs_camera"
+        android:description="@string/car_permission_desc_use_evs_camera"/>
+
+    <permission android:name="android.car.permission.STORAGE_ENCRYPTION_BINDING_SEED"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_encryption_binding_seed"
+        android:description="@string/car_permission_desc_encryption_binding_seed"/>
+
+    <permission android:name="android.car.permission.READ_CAR_POWER_POLICY"
+        android:protectionLevel="normal"
+        android:label="@string/car_permission_label_read_car_power_policy"
+        android:description="@string/car_permission_desc_read_car_power_policy"/>
+
+    <permission android:name="android.car.permission.CAR_EPOCH_TIME"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_car_epoch_time"
+        android:description="@string/car_permission_desc_car_epoch_time"/>
+
+    <permission android:name="android.car.permission.CONTROL_CAR_WATCHDOG_CONFIG"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_control_car_watchdog_config"
+        android:description="@string/car_permission_desc_control_car_watchdog_config"/>
+
+    <permission android:name="android.car.permission.TEMPLATE_RENDERER"
+        android:protectionLevel="signature|privileged"
+        android:label="@string/car_permission_label_template_renderer"
+        android:description="@string/car_permission_desc_template_renderer"/>
+
+    <permission android:name="android.car.permission.CAR_MONITOR_INPUT"
+        android:protectionLevel="signature"
+        android:label="@string/car_permission_label_monitor_input"
+        android:description="@string/car_permission_desc_monitor_input"/>
+
     <uses-permission android:name="android.permission.CALL_PHONE"/>
     <uses-permission android:name="android.permission.DEVICE_POWER"/>
     <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"/>
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index ee0f202..67da230 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -443,20 +443,6 @@
 
             click(By.text(permissionLabel))
 
-            // Watch does not show an alert dialog when the user turns on permission, only when they
-            // turns it off.
-            if (isWatch) {
-                try {
-                    if (waitFindObjectOrNull(By.text(permissionLabel), 1000) != null) {
-                        continue
-                    }
-                } catch (e: StaleObjectException) {
-                    // It sometimes causes StaleObjectException when screen changes due to click
-                    // It should be ignored, because it depends on timing
-                    Log.w("CtsPermission3TestCases", "Caught StaleObjectException")
-                }
-            }
-
             val wasGranted = if (isAutomotive) {
                 // Automotive doesn't support one time permissions, and thus
                 // won't show an "Ask every time" message
@@ -557,7 +543,7 @@
         }
 
     private fun isMediaStorageButton(permission: String, targetSdk: Int): Boolean =
-            if (isTv) {
+            if (isTv || isWatch) {
                 false
             } else {
                 when (permission) {
@@ -571,7 +557,7 @@
             }
 
     private fun isAllStorageButton(permission: String, targetSdk: Int): Boolean =
-            if (isTv) {
+            if (isTv || isWatch) {
                 false
             } else {
                 when (permission) {
diff --git a/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java b/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java
index 97cc62a..49471aa 100644
--- a/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java
+++ b/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java
@@ -29,6 +29,7 @@
 import android.net.Uri;
 import android.provider.BaseColumns;
 import android.provider.Telephony;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 
 /**
@@ -136,7 +137,8 @@
      * @throws Exception
      */
     public void testSmsBackupRestore() throws Exception {
-        if (!mHasFeature) {
+        TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
+        if (!mHasFeature || !telephonyManager.isSmsCapable()) {
             Log.i(TAG, "skipping testSmsBackupRestore");
             return;
         }
diff --git a/tests/tests/settings/src/android/settings/cts/SettingsHandlerTest.java b/tests/tests/settings/src/android/settings/cts/SettingsHandlerTest.java
index c60faa4..bc43731 100644
--- a/tests/tests/settings/src/android/settings/cts/SettingsHandlerTest.java
+++ b/tests/tests/settings/src/android/settings/cts/SettingsHandlerTest.java
@@ -49,7 +49,7 @@
         Uri uri = DocumentsContract.buildRootUri(MEDIA_PROVIDER_AUTHORITY, "videos_root");
         intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
 
-        assertThat(hasDefaultHandlerForIntent(intent)).isTrue();
+        assertThat(hasAtMostOneDefaultHandlerForIntent(intent)).isTrue();
     }
 
     @Test
@@ -58,7 +58,7 @@
         Uri uri = DocumentsContract.buildRootUri(MEDIA_PROVIDER_AUTHORITY, "images_root");
         intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
 
-        assertThat(hasDefaultHandlerForIntent(intent)).isTrue();
+        assertThat(hasAtMostOneDefaultHandlerForIntent(intent)).isTrue();
     }
 
     @Test
@@ -67,7 +67,7 @@
         Uri uri = DocumentsContract.buildRootUri(MEDIA_PROVIDER_AUTHORITY, "audio_root");
         intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
 
-        assertThat(hasDefaultHandlerForIntent(intent)).isTrue();
+        assertThat(hasAtMostOneDefaultHandlerForIntent(intent)).isTrue();
     }
 
     @Test
@@ -76,18 +76,25 @@
         Uri uri = DocumentsContract.buildRootUri(MEDIA_PROVIDER_AUTHORITY, "documents_root");
         intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
 
-        assertThat(hasDefaultHandlerForIntent(intent)).isTrue();
+        assertThat(hasAtMostOneDefaultHandlerForIntent(intent)).isTrue();
     }
 
     @Test
     public void oneDefaultHandlerForManageStorage() throws Exception {
         Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
 
-        assertThat(hasDefaultHandlerForIntent(intent)).isTrue();
+        assertThat(hasAtMostOneDefaultHandlerForIntent(intent)).isTrue();
     }
 
-    private boolean hasDefaultHandlerForIntent(Intent intent) {
+    private boolean hasAtMostOneDefaultHandlerForIntent(Intent intent) {
         ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, /* flags= */ 0);
+
+        if (resolveInfo == null) {
+            // Return true if no handlers can handle the intent, meaning that the specific platform
+            // does need to handle the intent.
+            return true;
+        }
+
         String packageName = resolveInfo.activityInfo.packageName;
         String activityName = resolveInfo.activityInfo.name;
         // If there are more than one handlers with no preferences set, the intent will resolve
diff --git a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java
index 27a3389..d012eb6 100644
--- a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java
+++ b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java
@@ -91,7 +91,8 @@
     }
 
     public List<SubscriptionInfo> getSubscriptionInfoForRemovableSims() {
-        if (mRemovableSubscriptionInfos == null) {
+        if (mRemovableSubscriptionInfos == null ||
+                mRemovableSubscriptionInfos.size() < mRemovableSimSlotCount) {
             initialize();
         }
         return mRemovableSubscriptionInfos;
diff --git a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_SimRecordsTest.java b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_SimRecordsTest.java
index 37ea8f6..9e0abfb 100644
--- a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_SimRecordsTest.java
+++ b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_SimRecordsTest.java
@@ -48,6 +48,7 @@
 
 import com.google.common.collect.ImmutableList;
 
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
@@ -156,6 +157,10 @@
 
     @Test
     public void queryFdn_noFdnRecords_returnsEmptyCursor() {
+        try (Cursor cursor =
+                     query(ElementaryFiles.getItemUri(mDefaultSubscriptionId, EF_FDN), null)) {
+            Assume.assumeTrue("SIM does not support FDN", cursor.moveToFirst());
+        }
         try (Cursor cursor = query(SimRecords.getContentUri(mDefaultSubscriptionId, EF_FDN),
                 null)) {
             assertThat(cursor).hasCount(0);
diff --git a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookRequirementsRule.java b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookRequirementsRule.java
index a7773b5..1a115cc 100644
--- a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookRequirementsRule.java
+++ b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookRequirementsRule.java
@@ -26,9 +26,12 @@
 
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.compatibility.common.util.PollingCheck;
+
 import org.junit.rules.ExternalResource;
 
 class SimPhonebookRequirementsRule extends ExternalResource {
+    private static final String TAG = "SimPhonebookRequirementsRule";
 
     private final int mMinimumSimCount;
 
@@ -50,10 +53,19 @@
         // DSDS or DSDA (e.g. crosshatch and blueline).
         assumeThat("not enough SIMs",
                 telephonyManager.getSupportedModemCount(), greaterThanOrEqualTo(mMinimumSimCount));
-        RemovableSims removableSims = new RemovableSims(context);
 
-        assumeThat(removableSims.getRemovableSimSlotCount(),
+        RemovableSims removableSims = new RemovableSims(context);
+        assumeThat("Device does not have enough SIMs.",
+                removableSims.getRemovableSimSlotCount(),
                 greaterThanOrEqualTo(mMinimumSimCount));
+        try {
+            // Poll for a bit in case it takes a while for the SIMs to be initialized.
+            PollingCheck.waitFor(30_000,
+                    () -> removableSims
+                            .getSubscriptionInfoForRemovableSims().size() >= mMinimumSimCount);
+        } catch (AssertionError e) {
+            // Swallowed here because the assert that follows validates the same thing.
+        }
         assertWithMessage("A SIM must be installed in each SIM slot")
                 .that(removableSims.getSubscriptionInfoForRemovableSims().size())
                 .isAtLeast(mMinimumSimCount);
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index ad9f709..96a07b3 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -42,6 +42,7 @@
     <uses-permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+    <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
 
     <application>
         <uses-library android:name="android.test.runner"/>
diff --git a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
index d63f8ef..0b74a9e 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
@@ -283,6 +283,12 @@
     public static final String ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING =
             "ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION ";
 
+    /**
+     * See {@link TelecomManager#ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION}
+     */
+    public static final String ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION_STRING =
+            "ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION ";
+
     private static final String COMMAND_SET_CALL_DIAGNOSTIC_SERVICE =
             "telecom set-call-diagnostic-service ";
 
diff --git a/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java b/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java
index 9be176b..8e2d759 100644
--- a/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java
+++ b/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.telecom.TelecomManager;
 import android.test.InstrumentationTestCase;
+import android.util.Log;
 
 /**
  * Verifies correct operation of TelecomManager APIs when the correct permissions have not been
@@ -89,4 +90,37 @@
                     TestUtils.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING);
         }
     }
+
+    public void testGetPhoneAccountCompatPermissions() throws Exception {
+        if (!TestUtils.shouldTestTelecom(mContext)) {
+            return;
+        }
+
+        try {
+            TestUtils.enableCompatCommand(getInstrumentation(),
+                    TestUtils.ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION_STRING);
+
+            try {
+                mTelecomManager.getPhoneAccount(TestUtils.TEST_DEFAULT_PHONE_ACCOUNT_HANDLE_1);
+                fail("TelecomManager#getPhoneAccount should require READ_PHONE_NUMBERS or "
+                        + "READ_PRIVILEGED_PHONE_STATE when "
+                        + "ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION is enabled");
+            } catch (SecurityException e) {
+                //expected
+            }
+
+            TestUtils.disableCompatCommand(getInstrumentation(),
+                    TestUtils.ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION_STRING);
+            try {
+                mTelecomManager.getPhoneAccount(TestUtils.TEST_DEFAULT_PHONE_ACCOUNT_HANDLE_1);
+            } catch (SecurityException e) {
+                fail("TelecomManager#getPhoneAccount shouldn't require READ_PHONE_NUMBERS or "
+                        + "READ_PRIVILEGED_PHONE_STATE when "
+                        + "ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION is disabled");
+            }
+        } finally {
+            TestUtils.resetCompatCommand(getInstrumentation(),
+                    TestUtils.ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION_STRING);
+        }
+    }
 }
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java b/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java
index 6d0a957..52b6245 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java
@@ -18,9 +18,6 @@
 
 import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
 
-import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
-import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
-
 import android.annotation.NonNull;
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -106,9 +103,7 @@
             throws Exception {
         mConnectivityManager = context.getSystemService(ConnectivityManager.class);
         mVcnManager = context.getSystemService(VcnManager.class);
-        mTestNetworkManager =
-                callWithShellPermissionIdentity(
-                        () -> context.getSystemService(TestNetworkManager.class));
+        mTestNetworkManager = context.getSystemService(TestNetworkManager.class);
 
         try {
             final LinkAddress linkAddress =
@@ -116,49 +111,31 @@
                             localAddress,
                             localAddress instanceof Inet4Address ? IP4_PREFIX_LEN : IP6_PREFIX_LEN);
             final TestNetworkInterface tni =
-                    callWithShellPermissionIdentity(
-                            () -> {
-                                return mTestNetworkManager.createTunInterface(
-                                        Arrays.asList(linkAddress));
-                            });
+                    mTestNetworkManager.createTunInterface(Arrays.asList(linkAddress));
             tunFd = tni.getFileDescriptor();
             final String iface = tni.getInterfaceName();
 
-            vcnNetworkCallback =
-                    callWithShellPermissionIdentity(
-                            () -> {
-                                final NetworkRequest nr =
-                                        new NetworkRequest.Builder(TEST_NETWORK_REQUEST)
-                                                .setNetworkSpecifier(iface)
-                                                .build();
-                                final VcnTestNetworkCallback cb = new VcnTestNetworkCallback();
-                                mConnectivityManager.requestNetwork(nr, cb);
-                                return cb;
-                            });
+            final NetworkRequest nr =
+                    new NetworkRequest.Builder(TEST_NETWORK_REQUEST)
+                            .setNetworkSpecifier(iface)
+                            .build();
+            vcnNetworkCallback = new VcnTestNetworkCallback();
+            mConnectivityManager.requestNetwork(nr, vcnNetworkCallback);
 
             final NetworkCapabilities nc =
                     createNetworkCapabilitiesForIface(iface, isMetered, subIds);
             final LinkProperties lp = createLinkPropertiesForIface(iface, mtu);
 
-            mTestNetworkAgent =
-                    callWithShellPermissionIdentity(
-                            () -> {
-                                final VcnNetworkPolicyResult policy =
-                                        mVcnManager.applyVcnNetworkPolicy(nc, lp);
-                                if (policy.isTeardownRequested()) {
-                                    throw new IllegalStateException("Restart requested in bringup");
-                                }
+            final VcnNetworkPolicyResult policy = mVcnManager.applyVcnNetworkPolicy(nc, lp);
+            if (policy.isTeardownRequested()) {
+                throw new IllegalStateException("Restart requested in bringup");
+            }
 
-                                final TestNetworkAgent agent =
-                                        new TestNetworkAgent(
-                                                context,
-                                                Looper.getMainLooper(),
-                                                policy.getNetworkCapabilities(),
-                                                lp);
-                                agent.register();
-                                agent.markConnected();
-                                return agent;
-                            });
+            mTestNetworkAgent =
+                    new TestNetworkAgent(
+                            context, Looper.getMainLooper(), policy.getNetworkCapabilities(), lp);
+            mTestNetworkAgent.register();
+            mTestNetworkAgent.markConnected();
 
             tunNetwork = vcnNetworkCallback.waitForAvailable();
             mCloseGuard.open(TAG);
@@ -232,42 +209,40 @@
     @Override
     public void close() {
         mCloseGuard.close();
-        runWithShellPermissionIdentity(
-                () -> {
-                    if (vcnNetworkCallback != null) {
-                        try {
-                            mConnectivityManager.unregisterNetworkCallback(vcnNetworkCallback);
-                        } catch (Exception e) {
-                            Log.e(TAG, "Failed to unregister Network CB", e);
-                        }
-                    }
 
-                    if (mTestNetworkAgent != null) {
-                        synchronized (mTestNetworkAgent) {
-                            try {
-                                mTestNetworkAgent.teardown();
-                            } catch (Exception e) {
-                                Log.e(TAG, "Failed to unregister TestNetworkAgent", e);
-                            }
-                        }
-                    }
+        if (vcnNetworkCallback != null) {
+            try {
+                mConnectivityManager.unregisterNetworkCallback(vcnNetworkCallback);
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to unregister Network CB", e);
+            }
+        }
 
-                    if (tunNetwork != null) {
-                        try {
-                            mTestNetworkManager.teardownTestNetwork(tunNetwork);
-                        } catch (Exception e) {
-                            Log.e(TAG, "Failed to tear down Test Network", e);
-                        }
-                    }
+        if (mTestNetworkAgent != null) {
+            synchronized (mTestNetworkAgent) {
+                try {
+                    mTestNetworkAgent.teardown();
+                } catch (Exception e) {
+                    Log.e(TAG, "Failed to unregister TestNetworkAgent", e);
+                }
+            }
+        }
 
-                    if (tunFd != null) {
-                        try {
-                            tunFd.close();
-                        } catch (Exception e) {
-                            Log.e(TAG, "Failed to close Test Network FD", e);
-                        }
-                    }
-                });
+        if (tunNetwork != null) {
+            try {
+                mTestNetworkManager.teardownTestNetwork(tunNetwork);
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to tear down Test Network", e);
+            }
+        }
+
+        if (tunFd != null) {
+            try {
+                tunFd.close();
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to close Test Network FD", e);
+            }
+        }
     }
 
     @Override
@@ -321,11 +296,9 @@
 
         @Override
         public void onNetworkUnwanted() {
-            // Not guaranteed to be called from the same thread, so synchronize on this. The shell
-            // is needed for teardown because unregistering the VcnPolicyListener requires
-            // permission MANAGE_TEST_NETWORKS.
+            // Not guaranteed to be called from the same thread, so synchronize on this.
             synchronized (this) {
-                runWithShellPermissionIdentity(() -> teardown());
+                teardown();
             }
         }
 
@@ -353,24 +326,19 @@
         private class TestVcnNetworkPolicyChangeListener implements VcnNetworkPolicyChangeListener {
             @Override
             public void onPolicyChanged() {
-                runWithShellPermissionIdentity(
-                        () -> {
-                            synchronized (TestNetworkAgent.this) {
-                                final VcnNetworkPolicyResult policy =
-                                        mVcnManager.applyVcnNetworkPolicy(
-                                                mTestNetworkAgent.getNetworkCapabilities(),
-                                                mTestNetworkAgent.getLinkProperties());
-                                if (policy.isTeardownRequested()) {
-                                    Log.w(
-                                            POLICY_LISTENER_TAG,
-                                            "network teardown requested on policy change");
-                                    teardown();
-                                    return;
-                                }
+                synchronized (TestNetworkAgent.this) {
+                    final VcnNetworkPolicyResult policy =
+                            mVcnManager.applyVcnNetworkPolicy(
+                                    mTestNetworkAgent.getNetworkCapabilities(),
+                                    mTestNetworkAgent.getLinkProperties());
+                    if (policy.isTeardownRequested()) {
+                        Log.w(POLICY_LISTENER_TAG, "network teardown requested on policy change");
+                        teardown();
+                        return;
+                    }
 
-                                updateNetworkCapabilities(policy.getNetworkCapabilities());
-                            }
-                        });
+                    updateNetworkCapabilities(policy.getNetworkCapabilities());
+                }
             }
         }
     }
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
index 9bf818d..7fec001 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
@@ -23,6 +23,8 @@
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 
 import static org.junit.Assert.assertEquals;
@@ -96,12 +98,19 @@
     @Before
     public void setUp() throws Exception {
         assumeTrue(mContext.getPackageManager().hasSystemFeature(FEATURE_TELEPHONY));
+
+        getInstrumentation().getUiAutomation().adoptShellPermissionIdentity();
     }
 
     @After
     public void tearDown() throws Exception {
-        if (mTestNetworkWrapper != null) {
-            mTestNetworkWrapper.close();
+        try {
+            if (mTestNetworkWrapper != null) {
+                mTestNetworkWrapper.close();
+                mTestNetworkWrapper = null;
+            }
+        } finally {
+            getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
         }
     }
 
@@ -172,6 +181,9 @@
     @Test(expected = SecurityException.class)
     public void testAddVcnNetworkPolicyChangeListener_noNetworkFactoryPermission()
             throws Exception {
+        // Drop shell permission identity to test unpermissioned behavior.
+        getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
+
         final TestVcnNetworkPolicyChangeListener listener =
                 new TestVcnNetworkPolicyChangeListener();
 
@@ -192,6 +204,9 @@
 
     @Test(expected = SecurityException.class)
     public void testApplyVcnNetworkPolicy_noNetworkFactoryPermission() throws Exception {
+        // Drop shell permission identity to test unpermissioned behavior.
+        getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
+
         final NetworkCapabilities nc = new NetworkCapabilities.Builder().build();
         final LinkProperties lp = new LinkProperties();
 
@@ -334,7 +349,7 @@
                 true /* expectNotVcnManaged */,
                 false /* expectNotMetered */);
 
-        CarrierPrivilegeUtils.withCarrierPrivileges(mContext, subId, () -> {
+        CarrierPrivilegeUtils.withCarrierPrivilegesForShell(mContext, subId, () -> {
             SubscriptionGroupUtils.withEphemeralSubscriptionGroup(mContext, subId, (subGrp) -> {
                 mVcnManager.setVcnConfig(subGrp, buildVcnConfig());
 
diff --git a/tests/tests/voiceinteraction/Android.bp b/tests/tests/voiceinteraction/Android.bp
index df37450..9ba5e42 100644
--- a/tests/tests/voiceinteraction/Android.bp
+++ b/tests/tests/voiceinteraction/Android.bp
@@ -24,6 +24,7 @@
         "ctstestrunner-axt",
         "compatibility-device-util-axt",
         "androidx.test.ext.junit",
+        "testng",
     ],
     srcs: [
         "src/**/*.java",
diff --git a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
index 2aaf0cc..7ec2d60 100644
--- a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
+++ b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
@@ -18,6 +18,8 @@
 import android.app.VoiceInteractor.PickOptionRequest.Option;
 import android.content.LocusId;
 import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -44,6 +46,9 @@
 
     public static final long OPERATION_TIMEOUT_MS = 5000;
 
+    /** CDD restricts the max size of each successful hotword result is 100 bytes. */
+    public static final int MAX_HOTWORD_DETECTED_RESULT_SIZE = 100;
+
     /** Decide which VoiceInteractionService should be started for testing. */
     public static final int HOTWORD_DETECTION_SERVICE_NONE = 0;
     public static final int HOTWORD_DETECTION_SERVICE_BASIC = 1;
@@ -227,4 +232,22 @@
         }
         return false;
     }
+
+    public static int getParcelableSize(Parcelable parcelable) {
+        final Parcel p = Parcel.obtain();
+        parcelable.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        final int size = p.dataSize();
+        p.recycle();
+        return size;
+    }
+
+    public static int bitCount(int value) {
+        int bits = 0;
+        while (value > 0) {
+            bits++;
+            value = value >> 1;
+        }
+        return bits;
+    }
 }
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
index da8c6e8..b23d0ae 100644
--- a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
@@ -58,7 +58,27 @@
         // TODO: Check the capture session (needs to be reflectively accessed).
         byte[] data = eventPayload.getTriggerAudio();
         if (data != null && data.length > 0) {
-            callback.onDetected(DETECTED_RESULT);
+            // Create the unaccepted HotwordDetectedResult first to test the protection in the
+            // onDetected callback function of HotwordDetectionService. When the bundle data of
+            // HotwordDetectedResult is larger than max bundle size, it will throw the
+            // IllegalArgumentException.
+            PersistableBundle persistableBundle = new PersistableBundle();
+            HotwordDetectedResult hotwordDetectedResult =
+                    new HotwordDetectedResult.Builder()
+                            .setExtras(persistableBundle)
+                            .build();
+            int key = 0;
+            do {
+                persistableBundle.putInt(Integer.toString(key), 0);
+                key++;
+            } while (Utils.getParcelableSize(persistableBundle)
+                    <= HotwordDetectedResult.getMaxBundleSize());
+
+            try {
+                callback.onDetected(hotwordDetectedResult);
+            } catch (IllegalArgumentException e) {
+                callback.onDetected(DETECTED_RESULT);
+            }
         } else {
             callback.onRejected(REJECTED_RESULT);
         }
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectedResultTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectedResultTest.java
index 3e245de..81254fdb 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectedResultTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectedResultTest.java
@@ -18,10 +18,14 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.testng.Assert.assertThrows;
+
+import android.media.AudioRecord;
 import android.media.MediaSyncEvent;
 import android.os.Parcel;
 import android.os.PersistableBundle;
 import android.service.voice.HotwordDetectedResult;
+import android.voiceinteraction.common.Utils;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
@@ -33,17 +37,93 @@
 
     @Test
     public void testHotwordDetectedResult_getMaxBundleSize() throws Exception {
-        assertThat(HotwordDetectedResult.getMaxBundleSize()).isEqualTo(50);
+        assertThat(HotwordDetectedResult.getMaxBundleSize() >= 0).isTrue();
+    }
+
+    @Test
+    public void testHotwordDetectedResult_totalSize() throws Exception {
+        final int bitsForConfidenceLevel = Utils.bitCount(
+                HotwordDetectedResult.CONFIDENCE_LEVEL_VERY_HIGH);
+        final int bitsForHotwordOffsetMillis = Integer.SIZE;
+        final int bitsForHotwordDurationMillis = Integer.SIZE;
+        final int bitsForAudioChannel = Integer.SIZE;
+        final int bitsForHotwordDetectionPersonalized = 1;
+        final int bitsForScore = Utils.bitCount(HotwordDetectedResult.getMaxScore());
+        final int bitsForPersonalizedScore = Utils.bitCount(HotwordDetectedResult.getMaxScore());
+        final int bitsForHotwordPhraseId = Utils.bitCount(
+                HotwordDetectedResult.getMaxHotwordPhraseId());
+
+        final int totalSize =
+                bitsForConfidenceLevel + bitsForHotwordOffsetMillis + bitsForHotwordDurationMillis
+                        + bitsForAudioChannel + bitsForHotwordDetectionPersonalized + bitsForScore
+                        + bitsForPersonalizedScore + bitsForHotwordPhraseId
+                        + HotwordDetectedResult.getMaxBundleSize() * Byte.SIZE;
+
+        assertThat(totalSize <= Utils.MAX_HOTWORD_DETECTED_RESULT_SIZE * Byte.SIZE).isTrue();
+    }
+
+    @Test
+    public void testHotwordDetectedResult_bundleExceedMaxBundleSize() throws Exception {
+        final PersistableBundle persistableBundle = new PersistableBundle();
+        int key = 0;
+        do {
+            persistableBundle.putInt(Integer.toString(key), 0);
+            key++;
+        } while (Utils.getParcelableSize(persistableBundle)
+                <= HotwordDetectedResult.getMaxBundleSize());
+
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setExtras(persistableBundle).build());
     }
 
     @Test
     public void testHotwordDetectedResult_getMaxHotwordPhraseId() throws Exception {
-        assertThat(HotwordDetectedResult.getMaxHotwordPhraseId()).isEqualTo(63);
+        assertThat(HotwordDetectedResult.getMaxHotwordPhraseId() >= 63).isTrue();
+    }
+
+    @Test
+    public void testHotwordDetectedResult_setInvalidHotwordPhraseId() throws Exception {
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setHotwordPhraseId(-1).build());
+
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setHotwordPhraseId(
+                        HotwordDetectedResult.getMaxHotwordPhraseId() + 1).build());
     }
 
     @Test
     public void testHotwordDetectedResult_getMaxScore() throws Exception {
-        assertThat(HotwordDetectedResult.getMaxScore()).isEqualTo(255);
+        assertThat(HotwordDetectedResult.getMaxScore() >= 255).isTrue();
+    }
+
+    @Test
+    public void testHotwordDetectedResult_setInvalidScore() throws Exception {
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setScore(-1).build());
+
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setScore(
+                        HotwordDetectedResult.getMaxScore() + 1).build());
+    }
+
+    @Test
+    public void testHotwordDetectedResult_setInvalidPersonalizedScore() throws Exception {
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setPersonalizedScore(-1).build());
+
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setPersonalizedScore(
+                        HotwordDetectedResult.getMaxScore() + 1).build());
+    }
+
+    @Test
+    public void testHotwordDetectedResult_setInvalidHotwordDurationMillis() throws Exception {
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setHotwordDurationMillis(-1).build());
+
+        assertThrows(IllegalArgumentException.class,
+                () -> new HotwordDetectedResult.Builder().setHotwordDurationMillis(
+                        (int) AudioRecord.getMaxSharedAudioHistoryMillis() + 1).build());
     }
 
     @Test